github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/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  }