go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/config/impl/resolving/resolving.go (about) 1 // Copyright 2020 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package resolving implements an interface that resolves ${var} placeholders 16 // in config set names and file paths before forwarding calls to some other 17 // interface. 18 package resolving 19 20 import ( 21 "context" 22 23 "go.chromium.org/luci/common/errors" 24 "go.chromium.org/luci/config" 25 "go.chromium.org/luci/config/vars" 26 ) 27 28 // New creates a config.Interface that resolves ${var} placeholders in config 29 // set names and file paths before forwarding calls to `next`. 30 func New(vars *vars.VarSet, next config.Interface) config.Interface { 31 return &resolvingInterface{vars, next} 32 } 33 34 type resolvingInterface struct { 35 vars *vars.VarSet 36 next config.Interface 37 } 38 39 func (r *resolvingInterface) configSet(ctx context.Context, cs config.Set) (config.Set, error) { 40 out, err := r.vars.RenderTemplate(ctx, string(cs)) 41 if err != nil { 42 return "", errors.Annotate(err, "bad configSet %q", cs).Err() 43 } 44 return config.Set(out), nil 45 } 46 47 func (r *resolvingInterface) path(ctx context.Context, p string) (string, error) { 48 out, err := r.vars.RenderTemplate(ctx, p) 49 if err != nil { 50 return "", errors.Annotate(err, "bad path %q", p).Err() 51 } 52 return out, nil 53 } 54 55 func (r *resolvingInterface) GetConfig(ctx context.Context, configSet config.Set, path string, metaOnly bool) (*config.Config, error) { 56 configSet, err := r.configSet(ctx, configSet) 57 if err != nil { 58 return nil, err 59 } 60 path, err = r.path(ctx, path) 61 if err != nil { 62 return nil, err 63 } 64 return r.next.GetConfig(ctx, configSet, path, metaOnly) 65 } 66 67 func (r *resolvingInterface) GetConfigs(ctx context.Context, configSet config.Set, filter func(path string) bool, metaOnly bool) (map[string]config.Config, error) { 68 configSet, err := r.configSet(ctx, configSet) 69 if err != nil { 70 return nil, err 71 } 72 return r.next.GetConfigs(ctx, configSet, filter, metaOnly) 73 } 74 75 func (r *resolvingInterface) GetProjectConfigs(ctx context.Context, path string, metaOnly bool) ([]config.Config, error) { 76 path, err := r.path(ctx, path) 77 if err != nil { 78 return nil, err 79 } 80 return r.next.GetProjectConfigs(ctx, path, metaOnly) 81 } 82 83 func (r *resolvingInterface) GetProjects(ctx context.Context) ([]config.Project, error) { 84 return r.next.GetProjects(ctx) 85 } 86 87 func (r *resolvingInterface) ListFiles(ctx context.Context, configSet config.Set) ([]string, error) { 88 configSet, err := r.configSet(ctx, configSet) 89 if err != nil { 90 return nil, err 91 } 92 return r.next.ListFiles(ctx, configSet) 93 } 94 95 func (r *resolvingInterface) Close() error { 96 if r.next != nil { 97 return r.next.Close() 98 } 99 return nil 100 }