| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. |
| 4 |
| 5 package cfgclient |
| 6 |
| 7 import ( |
| 8 "net/url" |
| 9 |
| 10 "github.com/luci/luci-go/common/config" |
| 11 "github.com/luci/luci-go/common/errors" |
| 12 "github.com/luci/luci-go/luci_config/common/cfgtypes" |
| 13 "github.com/luci/luci-go/luci_config/server/cfgclient/backend" |
| 14 |
| 15 "golang.org/x/net/context" |
| 16 ) |
| 17 |
| 18 // ErrNoConfig is a sentinel error returned by Get when the requested |
| 19 // configuration is not found. |
| 20 // |
| 21 // This is an alias of github.com/luci/luci-go/common/config.ErrNoConfig for |
| 22 // backward compatibility. |
| 23 var ErrNoConfig = config.ErrNoConfig |
| 24 |
| 25 // Meta is metadata about a single configuration file. |
| 26 // |
| 27 // This differs from backend.Meta in that it uses the ConfigSet type for the |
| 28 // ConfigSet field. |
| 29 type Meta struct { |
| 30 // ConfigSet is the item's config set. |
| 31 ConfigSet cfgtypes.ConfigSet |
| 32 // Path is the item's path within its config set. |
| 33 Path string |
| 34 |
| 35 // ContentHash is the content hash. |
| 36 ContentHash string |
| 37 // Revision is the revision string. |
| 38 Revision string |
| 39 } |
| 40 |
| 41 // Authority is the authority on whose behalf a request is operating. |
| 42 type Authority backend.Authority |
| 43 |
| 44 var ( |
| 45 // AsAnonymous requests config data as an anonymous user. |
| 46 // |
| 47 // Corresponds to auth.NoAuth. |
| 48 AsAnonymous = Authority(backend.AsAnonymous) |
| 49 |
| 50 // AsService requests config data as the currently-running service. |
| 51 // |
| 52 // Corresponds to auth.AsSelf. |
| 53 AsService = Authority(backend.AsService) |
| 54 |
| 55 // AsUser requests config data as the currently logged-in user. |
| 56 // |
| 57 // Corresponds to auth.AsUser. |
| 58 AsUser = Authority(backend.AsUser) |
| 59 ) |
| 60 |
| 61 // ServiceURL returns the URL of the config service. |
| 62 func ServiceURL(c context.Context) url.URL { return backend.Get(c).ServiceURL(c)
} |
| 63 |
| 64 // Get retrieves a single configuration file. |
| 65 // |
| 66 // r, if supplied, is a MultiResolver that will load the configuration data. |
| 67 // If nil, the configuration data will be discarded (useful if you only care |
| 68 // about metas). |
| 69 // |
| 70 // meta, if not nil, will have the configuration's Meta loaded into it on |
| 71 // success. |
| 72 func Get(c context.Context, a Authority, cs cfgtypes.ConfigSet, path string, r R
esolver, meta *Meta) error { |
| 73 be := backend.Get(c) |
| 74 |
| 75 params := backend.Params{ |
| 76 Authority: backend.Authority(a), |
| 77 Content: true, |
| 78 } |
| 79 |
| 80 if fr, ok := r.(FormattingResolver); ok { |
| 81 params.FormatSpec = fr.Format() |
| 82 } |
| 83 |
| 84 item, err := be.Get(c, string(cs), path, params) |
| 85 if err != nil { |
| 86 return err |
| 87 } |
| 88 |
| 89 if meta != nil { |
| 90 *meta = *makeMeta(&item.Meta) |
| 91 } |
| 92 if r == nil { |
| 93 return nil |
| 94 } |
| 95 return r.Resolve(item) |
| 96 } |
| 97 |
| 98 // Projects retrieves all named project configurations. |
| 99 // |
| 100 // r, if supplied, is a MultiResolver that will load the configuration data. |
| 101 // If nil, the configuration data will be discarded (useful if you only care |
| 102 // about metas). If the MultiResolver operates on a slice (which it probably |
| 103 // will), each meta and/or error index will correspond to its slice index. |
| 104 // |
| 105 // If meta is not nil, it will be populated with a slice of *Meta entries |
| 106 // for each loaded configuration, in the same order that r receives them. If |
| 107 // r resolves to a slice, the indexes for each resolved slice entry and meta |
| 108 // entry should align unless r is doing something funky. |
| 109 // |
| 110 // Two types of failure may happen here. A systemic failure fails to load the |
| 111 // set of project configurations. This will be returned directly. |
| 112 // |
| 113 // A resolver failure happens when the configuratiokns load, but could not be |
| 114 // resolved. In this case, any successful resolutions and "meta" will be |
| 115 // populated and an errors.MultiError will be returned containing non-nil |
| 116 // errors at indices whose configs failed to resolve. |
| 117 func Projects(c context.Context, a Authority, path string, r MultiResolver, meta
*[]*Meta) error { |
| 118 return getAll(c, a, backend.GetAllProject, path, r, meta) |
| 119 } |
| 120 |
| 121 // Refs retrieves all named ref configurations. |
| 122 // |
| 123 // See Projects for individual argument descriptions. |
| 124 func Refs(c context.Context, a Authority, path string, r MultiResolver, meta *[]
*Meta) error { |
| 125 return getAll(c, a, backend.GetAllRef, path, r, meta) |
| 126 } |
| 127 |
| 128 func getAll(c context.Context, a Authority, t backend.GetAllTarget, path string,
r MultiResolver, |
| 129 meta *[]*Meta) error { |
| 130 |
| 131 be := backend.Get(c) |
| 132 |
| 133 params := backend.Params{ |
| 134 Authority: backend.Authority(a), |
| 135 Content: true, |
| 136 } |
| 137 |
| 138 if fr, ok := r.(FormattingResolver); ok { |
| 139 params.FormatSpec = fr.Format() |
| 140 } |
| 141 |
| 142 items, err := be.GetAll(c, t, path, params) |
| 143 if err != nil { |
| 144 return err |
| 145 } |
| 146 |
| 147 // Load our metas. |
| 148 if meta != nil { |
| 149 metaSlice := *meta |
| 150 if metaSlice == nil { |
| 151 metaSlice = make([]*Meta, 0, len(items)) |
| 152 } else { |
| 153 // Re-use the supplied slice. |
| 154 metaSlice = metaSlice[:0] |
| 155 } |
| 156 |
| 157 for _, item := range items { |
| 158 metaSlice = append(metaSlice, makeMeta(&item.Meta)) |
| 159 } |
| 160 |
| 161 *meta = metaSlice |
| 162 } |
| 163 |
| 164 if r == nil { |
| 165 return nil |
| 166 } |
| 167 |
| 168 // Resolve our items. If any individual resolution fails, return that fa
ilure |
| 169 // as a positional error in a MultiError. |
| 170 lme := errors.NewLazyMultiError(len(items)) |
| 171 r.PrepareMulti(len(items)) |
| 172 for i, it := range items { |
| 173 if err := r.ResolveItemAt(i, it); err != nil { |
| 174 lme.Assign(i, err) |
| 175 } |
| 176 } |
| 177 return lme.Get() |
| 178 } |
| 179 |
| 180 // GetConfigSetURL returns the URL where the specified ConfigSet is |
| 181 // configured. If the config set doesn't exist, ErrNoConfig will be returned. |
| 182 func GetConfigSetURL(c context.Context, a Authority, cs cfgtypes.ConfigSet) (url
.URL, error) { |
| 183 return backend.Get(c).ConfigSetURL(c, string(cs), backend.Params{ |
| 184 Authority: backend.Authority(a), |
| 185 }) |
| 186 } |
| 187 |
| 188 func makeMeta(b *backend.Meta) *Meta { |
| 189 return &Meta{ |
| 190 ConfigSet: cfgtypes.ConfigSet(b.ConfigSet), |
| 191 Path: b.Path, |
| 192 ContentHash: b.ContentHash, |
| 193 Revision: b.Revision, |
| 194 } |
| 195 } |
| OLD | NEW |