go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/configs/srvcfg/config.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 srvcfg provides service-wide configs. 16 package srvcfg 17 18 import ( 19 "context" 20 "regexp" 21 22 "go.chromium.org/luci/common/errors" 23 "go.chromium.org/luci/config" 24 "go.chromium.org/luci/config/server/cfgcache" 25 26 listenerpb "go.chromium.org/luci/cv/settings/listener" 27 ) 28 29 var ( 30 cachedListenerCfg = cfgcache.Register(&cfgcache.Entry{ 31 Path: "listener-settings.cfg", 32 Type: (*listenerpb.Settings)(nil), 33 }) 34 ) 35 36 // ImportConfig is called from a cron to import and cache all the configs. 37 func ImportConfig(ctx context.Context) error { 38 _, err := cachedListenerCfg.Update(ctx, nil) 39 return err 40 } 41 42 // GetListenerConfig loads cached Listener config. 43 // 44 // If meta is not nil, it will be updated with the meta of the loaded config. 45 func GetListenerConfig(ctx context.Context, meta *config.Meta) (*listenerpb.Settings, error) { 46 switch v, err := cachedListenerCfg.Get(ctx, meta); { 47 case err != nil: 48 return nil, err 49 default: 50 return v.(*listenerpb.Settings), nil 51 } 52 } 53 54 // SetTestListenerConfig is used in tests only. 55 func SetTestListenerConfig(ctx context.Context, ls *listenerpb.Settings, m *config.Meta) error { 56 return cachedListenerCfg.Set(ctx, ls, m) 57 } 58 59 // MakeListenerProjectChecker returns a function that checks if a given project 60 // is enabled in the Listener config. 61 func MakeListenerProjectChecker(ls *listenerpb.Settings) (isEnabled func(string) bool, err error) { 62 res, err := anchorRegexps(ls.GetDisabledProjectRegexps()) 63 if err != nil { 64 // Must be a bug in the validator. 65 return nil, errors.Annotate(err, "invalid disabled_project_regexps").Err() 66 } 67 return func(prj string) bool { 68 for _, re := range res { 69 if re.Match([]byte(prj)) { 70 return false 71 } 72 } 73 return true 74 }, nil 75 } 76 77 // anchorRegexps converts partial match regexs to full matches. 78 // 79 // Returns compiled regexps of them. 80 func anchorRegexps(partials []string) ([]*regexp.Regexp, error) { 81 var me errors.MultiError 82 var res []*regexp.Regexp 83 for _, p := range partials { 84 re, err := regexp.Compile("^" + p + "$") 85 me.MaybeAdd(err) 86 res = append(res, re) 87 } 88 if me.AsError() == nil { 89 return res, nil 90 } 91 return nil, me 92 } 93 94 // IsProjectEnabledInListener returns true if a given project is enabled 95 // in the cached Listener config. 96 func IsProjectEnabledInListener(ctx context.Context, project string) (bool, error) { 97 cfg, err := GetListenerConfig(ctx, nil) 98 if err != nil { 99 return false, err 100 } 101 chk, err := MakeListenerProjectChecker(cfg) 102 if err != nil { 103 return false, err 104 } 105 return chk(project), nil 106 }