github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/overlord/configstate/configcore/corecfg.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2017 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package configcore 21 22 import ( 23 "fmt" 24 "os" 25 "reflect" 26 "regexp" 27 28 "github.com/snapcore/snapd/overlord/configstate/config" 29 ) 30 31 var ( 32 Stdout = os.Stdout 33 Stderr = os.Stderr 34 35 validCertRegexp = `[\w](?:-?[\w])*` 36 validCertName = regexp.MustCompile(validCertRegexp).MatchString 37 validCertOption = regexp.MustCompile(`^core\.store-certs\.` + validCertRegexp + "$").MatchString 38 ) 39 40 // coreCfg returns the configuration value for the core snap. 41 func coreCfg(tr config.ConfGetter, key string) (result string, err error) { 42 var v interface{} = "" 43 if err := tr.Get("core", key, &v); err != nil && !config.IsNoOption(err) { 44 return "", err 45 } 46 // TODO: we could have a fully typed approach but at the 47 // moment we also always use "" to mean unset as well, this is 48 // the smallest change 49 return fmt.Sprintf("%v", v), nil 50 } 51 52 // supportedConfigurations contains a set of handled configuration keys. 53 // The actual values are populated by `init()` functions in each module. 54 var supportedConfigurations = make(map[string]bool, 32) 55 56 func validateBoolFlag(tr config.ConfGetter, flag string) error { 57 value, err := coreCfg(tr, flag) 58 if err != nil { 59 return err 60 } 61 switch value { 62 case "", "true", "false": 63 // noop 64 default: 65 return fmt.Errorf("%s can only be set to 'true' or 'false'", flag) 66 } 67 return nil 68 } 69 70 // plainCoreConfig carries a read-only copy of core config and implements 71 // config.ConfGetter interface. 72 type plainCoreConfig map[string]interface{} 73 74 // Get implements config.ConfGetter interface. 75 func (cfg plainCoreConfig) Get(snapName, key string, result interface{}) error { 76 if snapName != "core" { 77 return fmt.Errorf("internal error: expected core snap in Get(), %q was requested", snapName) 78 } 79 80 val, ok := cfg[key] 81 if !ok { 82 return &config.NoOptionError{SnapName: snapName, Key: key} 83 } 84 85 rv := reflect.ValueOf(result) 86 rv.Elem().Set(reflect.ValueOf(val)) 87 return nil 88 } 89 90 // GetPristine implements config.ConfGetter interface 91 // for plainCoreConfig, there are no "pristine" values, so just return nothing 92 // this has the effect that every setting will be viewed as "dirty" and needing 93 // to be applied 94 func (cfg plainCoreConfig) GetPristine(snapName, key string, result interface{}) error { 95 return nil 96 } 97 98 // GetMaybe implements config.ConfGetter interface. 99 func (cfg plainCoreConfig) GetMaybe(instanceName, key string, result interface{}) error { 100 err := cfg.Get(instanceName, key, result) 101 if err != nil && !config.IsNoOption(err) { 102 return err 103 } 104 return nil 105 } 106 107 // fsOnlyContext encapsulates extra options passed to individual core config 108 // handlers when configuration is applied to a specific root directory with 109 // FilesystemOnlyApply(). 110 type fsOnlyContext struct { 111 RootDir string 112 }