diff --git a/cmd/cloudinit/cloudinit.go b/cmd/cloudinit/cloudinit.go index e5e82e97..d65008bf 100644 --- a/cmd/cloudinit/cloudinit.go +++ b/cmd/cloudinit/cloudinit.go @@ -96,11 +96,7 @@ func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadat } func currentDatasource() (datasource.Datasource, error) { - cfg, err := rancherConfig.LoadConfig() - if err != nil { - log.WithFields(log.Fields{"err": err}).Error("Failed to read rancher config") - return nil, err - } + cfg := rancherConfig.LoadConfig() dss := getDatasources(cfg) if len(dss) == 0 { @@ -169,10 +165,7 @@ func fetchUserData() ([]byte, datasource.Metadata, error) { } func executeCloudConfig() error { - cc, err := rancherConfig.LoadConfig() - if err != nil { - return err - } + cc := rancherConfig.LoadConfig() if len(cc.SSHAuthorizedKeys) > 0 { authorizeSSHKeys("rancher", cc.SSHAuthorizedKeys, sshKeyName) diff --git a/cmd/control/env.go b/cmd/control/env.go index db2675f0..166c6ad3 100644 --- a/cmd/control/env.go +++ b/cmd/control/env.go @@ -12,10 +12,7 @@ import ( ) func envAction(c *cli.Context) error { - cfg, err := config.LoadConfig() - if err != nil { - log.Fatal(err) - } + cfg := config.LoadConfig() args := c.Args() if len(args) == 0 { diff --git a/cmd/control/install.go b/cmd/control/install.go index fed3a917..dbf6374a 100644 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -58,10 +58,7 @@ func installAction(c *cli.Context) error { } image := c.String("image") - cfg, err := config.LoadConfig() - if err != nil { - log.WithFields(log.Fields{"err": err}).Fatal("ros install: failed to load config") - } + cfg := config.LoadConfig() if image == "" { image = cfg.Rancher.Upgrade.Image + ":" + config.VERSION + config.SUFFIX } diff --git a/cmd/control/os.go b/cmd/control/os.go index 0c3823d3..ee9c3d9f 100644 --- a/cmd/control/os.go +++ b/cmd/control/os.go @@ -289,10 +289,6 @@ func parseBody(body []byte) (*Images, error) { } func getUpgradeUrl() (string, error) { - cfg, err := config.LoadConfig() - if err != nil { - return "", err - } - + cfg := config.LoadConfig() return cfg.Rancher.Upgrade.Url, nil } diff --git a/cmd/control/service.go b/cmd/control/service.go index 54992982..47a61832 100644 --- a/cmd/control/service.go +++ b/cmd/control/service.go @@ -18,11 +18,7 @@ type projectFactory struct { } func (p *projectFactory) Create(c *cli.Context) (project.APIProject, error) { - cfg, err := config.LoadConfig() - if err != nil { - return nil, err - } - + cfg := config.LoadConfig() return compose.GetProject(cfg, true) } @@ -92,10 +88,7 @@ func updateIncludedServices(cfg *config.CloudConfig) error { func disable(c *cli.Context) error { changed := false - cfg, err := config.LoadConfig() - if err != nil { - logrus.Fatal(err) - } + cfg := config.LoadConfig() for _, service := range c.Args() { if _, ok := cfg.Rancher.ServicesInclude[service]; !ok { @@ -107,7 +100,7 @@ func disable(c *cli.Context) error { } if changed { - if err = updateIncludedServices(cfg); err != nil { + if err := updateIncludedServices(cfg); err != nil { logrus.Fatal(err) } } @@ -117,10 +110,7 @@ func disable(c *cli.Context) error { func del(c *cli.Context) error { changed := false - cfg, err := config.LoadConfig() - if err != nil { - logrus.Fatal(err) - } + cfg := config.LoadConfig() for _, service := range c.Args() { if _, ok := cfg.Rancher.ServicesInclude[service]; !ok { @@ -131,7 +121,7 @@ func del(c *cli.Context) error { } if changed { - if err = updateIncludedServices(cfg); err != nil { + if err := updateIncludedServices(cfg); err != nil { logrus.Fatal(err) } } @@ -140,10 +130,7 @@ func del(c *cli.Context) error { } func enable(c *cli.Context) error { - cfg, err := config.LoadConfig() - if err != nil { - logrus.Fatal(err) - } + cfg := config.LoadConfig() var enabledServices []string @@ -163,7 +150,7 @@ func enable(c *cli.Context) error { logrus.Fatal(err) } - if err = updateIncludedServices(cfg); err != nil { + if err := updateIncludedServices(cfg); err != nil { logrus.Fatal(err) } } @@ -172,10 +159,7 @@ func enable(c *cli.Context) error { } func list(c *cli.Context) error { - cfg, err := config.LoadConfig() - if err != nil { - logrus.Fatal(err) - } + cfg := config.LoadConfig() clone := make(map[string]bool) for service, enabled := range cfg.Rancher.ServicesInclude { diff --git a/cmd/control/tlsconf.go b/cmd/control/tlsconf.go index 72d95715..f6d2ddd1 100644 --- a/cmd/control/tlsconf.go +++ b/cmd/control/tlsconf.go @@ -74,10 +74,7 @@ func writeCerts(generateServer bool, hostname []string, cfg *config.CloudConfig, } } - cfg, err := config.LoadConfig() - if err != nil { - return err - } + cfg = config.LoadConfig() if err := ioutil.WriteFile(certPath, []byte(cfg.Rancher.Docker.ServerCert), 0400); err != nil { return err @@ -112,10 +109,7 @@ func writeCaCerts(cfg *config.CloudConfig, caCertPath, caKeyPath string) error { } } - cfg, err := config.LoadConfig() - if err != nil { - return err - } + cfg = config.LoadConfig() if err := ioutil.WriteFile(caCertPath, []byte(cfg.Rancher.Docker.CACert), 0400); err != nil { return err @@ -170,11 +164,9 @@ func Generate(generateServer bool, outDir string, hostnames []string) error { } } - cfg, err := config.LoadConfig() - if err != nil { - return err - } - err = writeCaCerts(cfg, caCertPath, caKeyPath) + cfg := config.LoadConfig() + + err := writeCaCerts(cfg, caCertPath, caKeyPath) if err != nil { return err } diff --git a/cmd/network/network.go b/cmd/network/network.go index 3917d3f5..7d87a453 100644 --- a/cmd/network/network.go +++ b/cmd/network/network.go @@ -47,10 +47,7 @@ func Main() { } } - cfg, err := config.LoadConfig() - if err != nil { - log.Fatal(err) - } + cfg := config.LoadConfig() nameservers := cfg.Rancher.Network.Dns.Nameservers search := cfg.Rancher.Network.Dns.Search diff --git a/cmd/userdocker/main.go b/cmd/userdocker/main.go index d56977a5..ab3d9534 100644 --- a/cmd/userdocker/main.go +++ b/cmd/userdocker/main.go @@ -28,10 +28,7 @@ const ( ) func Main() { - cfg, err := config.LoadConfig() - if err != nil { - log.Fatal(err) - } + cfg := config.LoadConfig() if err := startDocker(cfg); err != nil { log.Fatal(err) diff --git a/compose/project.go b/compose/project.go index 61ae0cac..25877aff 100644 --- a/compose/project.go +++ b/compose/project.go @@ -22,11 +22,7 @@ import ( func CreateService(cfg *config.CloudConfig, name string, serviceConfig *composeConfig.ServiceConfigV1) (project.Service, error) { if cfg == nil { - var err error - cfg, err = config.LoadConfig() - if err != nil { - return nil, err - } + cfg = config.LoadConfig() } p, err := CreateServiceSet("once", cfg, map[string]*composeConfig.ServiceConfigV1{ @@ -195,11 +191,7 @@ func newCoreServiceProject(cfg *config.CloudConfig, useNetwork bool) (*project.P p.AddListener(projectEvents) p.ReloadCallback = func() error { - var err error - cfg, err = config.LoadConfig() - if err != nil { - return err - } + cfg = config.LoadConfig() environmentLookup.SetConfig(cfg) diff --git a/config/config.go b/config/config.go index a8e64937..24737d08 100644 --- a/config/config.go +++ b/config/config.go @@ -72,11 +72,11 @@ func StringifyValues(data map[interface{}]interface{}) map[interface{}]interface } func Merge(bytes []byte) error { - data, err := readConfig(bytes, false) + data, err := readConfigs(bytes, false, true) if err != nil { return err } - existing, err := readConfig(nil, false, CloudConfigFile) + existing, err := readConfigs(nil, false, true, CloudConfigFile) if err != nil { return err } @@ -84,7 +84,7 @@ func Merge(bytes []byte) error { } func Export(private, full bool) (string, error) { - rawCfg, err := LoadRawConfig(full) + rawCfg := loadRawDiskConfig(full) if !private { rawCfg = filterPrivateKeys(rawCfg) } @@ -94,10 +94,7 @@ func Export(private, full bool) (string, error) { } func Get(key string) (interface{}, error) { - cfg, err := LoadConfig() - if err != nil { - return nil, err - } + cfg := LoadConfig() data := map[interface{}]interface{}{} if err := util.ConvertIgnoreOmitEmpty(cfg, &data); err != nil { @@ -109,13 +106,11 @@ func Get(key string) (interface{}, error) { } func Set(key string, value interface{}) error { - data := map[interface{}]interface{}{} - _, data = getOrSetVal(key, data, value) - - existing, err := readConfig(nil, false, CloudConfigFile) + existing, err := readConfigs(nil, false, true, CloudConfigFile) if err != nil { return err } - return WriteToFile(util.Merge(existing, data), CloudConfigFile) + _, modified := getOrSetVal(key, existing, value) + return WriteToFile(modified, CloudConfigFile) } diff --git a/config/disk.go b/config/disk.go index 82695243..630bb11a 100644 --- a/config/disk.go +++ b/config/disk.go @@ -15,65 +15,51 @@ import ( "github.com/rancher/os/util" ) -func NewConfig() map[interface{}]interface{} { - osConfig, _ := readConfig(nil, true, OsConfigFile, OemConfigFile) - return osConfig -} - func ReadConfig(bytes []byte, substituteMetadataVars bool, files ...string) (*CloudConfig, error) { - if data, err := readConfig(bytes, substituteMetadataVars, files...); err == nil { - c := &CloudConfig{} - if err := util.Convert(data, c); err != nil { - return nil, err - } - c, _ = amendNils(c) - c, _ = amendContainerNames(c) - return c, nil - } else { + data, err := readConfigs(bytes, substituteMetadataVars, true, files...) + if err != nil { return nil, err } + + c := &CloudConfig{} + if err := util.Convert(data, c); err != nil { + return nil, err + } + c = amendNils(c) + c = amendContainerNames(c) + return c, nil } -func LoadRawConfig(full bool) (map[interface{}]interface{}, error) { - var base map[interface{}]interface{} +func loadRawDiskConfig(full bool) map[interface{}]interface{} { + var rawCfg map[interface{}]interface{} if full { - base = NewConfig() + rawCfg, _ = readConfigs(nil, true, false, OsConfigFile, OemConfigFile) } - user, err := readConfigs() - if err != nil { - return nil, err - } - cmdline, err := readCmdline() - if err != nil { - return nil, err - } - merged := util.Merge(base, util.Merge(user, cmdline)) - merged, err = applyDebugFlags(merged) - if err != nil { - return nil, err - } - return mergeMetadata(merged, readMetadata()), nil + + files := append(CloudConfigDirFiles(), CloudConfigFile) + additionalCfgs, _ := readConfigs(nil, true, false, files...) + + return util.Merge(rawCfg, additionalCfgs) } -func LoadConfig() (*CloudConfig, error) { - rawCfg, err := LoadRawConfig(true) - if err != nil { - return nil, err - } +func loadRawConfig() map[interface{}]interface{} { + rawCfg := loadRawDiskConfig(true) + rawCfg = util.Merge(rawCfg, readCmdline()) + rawCfg = applyDebugFlags(rawCfg) + return mergeMetadata(rawCfg, readMetadata()) +} + +func LoadConfig() *CloudConfig { + rawCfg := loadRawConfig() cfg := &CloudConfig{} if err := util.Convert(rawCfg, cfg); err != nil { - return nil, err + log.Errorf("Failed to parse configuration: %s", err) + return &CloudConfig{} } - cfg, err = amendNils(cfg) - if err != nil { - return nil, err - } - cfg, err = amendContainerNames(cfg) - if err != nil { - return nil, err - } - return cfg, nil + cfg = amendNils(cfg) + cfg = amendContainerNames(cfg) + return cfg } func CloudConfigDirFiles() []string { @@ -98,10 +84,10 @@ func CloudConfigDirFiles() []string { return finalFiles } -func applyDebugFlags(rawCfg map[interface{}]interface{}) (map[interface{}]interface{}, error) { +func applyDebugFlags(rawCfg map[interface{}]interface{}) map[interface{}]interface{} { cfg := &CloudConfig{} if err := util.Convert(rawCfg, cfg); err != nil { - return nil, err + return rawCfg } if cfg.Rancher.Debug { @@ -116,7 +102,7 @@ func applyDebugFlags(rawCfg map[interface{}]interface{}) (map[interface{}]interf _, rawCfg = getOrSetVal("rancher.docker.args", rawCfg, cfg.Rancher.Docker.Args) _, rawCfg = getOrSetVal("rancher.system_docker.args", rawCfg, cfg.Rancher.SystemDocker.Args) - return rawCfg, nil + return rawCfg } // mergeMetadata merges certain options from md (meta-data from the datasource) @@ -172,35 +158,26 @@ func readMetadata() datasource.Metadata { return metadata } -func readConfigs() (map[interface{}]interface{}, error) { - files := append(CloudConfigDirFiles(), CloudConfigFile) - data, err := readConfig(nil, true, files...) - if err != nil { - return nil, err - } - return data, nil -} - -func readCmdline() (map[interface{}]interface{}, error) { +func readCmdline() map[interface{}]interface{} { log.Debug("Reading config cmdline") cmdLine, err := ioutil.ReadFile("/proc/cmdline") if err != nil { log.WithFields(log.Fields{"err": err}).Error("Failed to read kernel params") - return nil, err + return nil } if len(cmdLine) == 0 { - return nil, nil + return nil } log.Debugf("Config cmdline %s", cmdLine) cmdLineObj := parseCmdline(strings.TrimSpace(string(cmdLine))) - return cmdLineObj, nil + return cmdLineObj } -func amendNils(c *CloudConfig) (*CloudConfig, error) { +func amendNils(c *CloudConfig) *CloudConfig { t := *c if t.Rancher.Environment == nil { t.Rancher.Environment = map[string]string{} @@ -217,10 +194,10 @@ func amendNils(c *CloudConfig) (*CloudConfig, error) { if t.Rancher.ServicesInclude == nil { t.Rancher.ServicesInclude = map[string]bool{} } - return &t, nil + return &t } -func amendContainerNames(c *CloudConfig) (*CloudConfig, error) { +func amendContainerNames(c *CloudConfig) *CloudConfig { for _, scm := range []map[string]*composeConfig.ServiceConfigV1{ c.Rancher.Autoformat, c.Rancher.BootstrapContainers, @@ -230,7 +207,7 @@ func amendContainerNames(c *CloudConfig) (*CloudConfig, error) { v.ContainerName = k } } - return c, nil + return c } func WriteToFile(data interface{}, filename string) error { @@ -242,7 +219,7 @@ func WriteToFile(data interface{}, filename string) error { return ioutil.WriteFile(filename, content, 400) } -func readConfig(bytes []byte, substituteMetadataVars bool, files ...string) (map[interface{}]interface{}, error) { +func readConfigs(bytes []byte, substituteMetadataVars, returnErr bool, files ...string) (map[interface{}]interface{}, error) { // You can't just overlay yaml bytes on to maps, it won't merge, but instead // just override the keys and not merge the map values. left := make(map[interface{}]interface{}) @@ -250,7 +227,11 @@ func readConfig(bytes []byte, substituteMetadataVars bool, files ...string) (map for _, file := range files { content, err := readConfigFile(file) if err != nil { - return nil, err + if returnErr { + return nil, err + } + log.Errorf("Failed to read config file %s: %s", file, err) + continue } if len(content) == 0 { continue @@ -262,24 +243,53 @@ func readConfig(bytes []byte, substituteMetadataVars bool, files ...string) (map right := make(map[interface{}]interface{}) err = yaml.Unmarshal(content, &right) if err != nil { - return nil, err + if returnErr { + return nil, err + } + log.Errorf("Failed to parse config file %s: %s", file, err) + continue + } + + // Verify there are no issues converting to CloudConfig + c := &CloudConfig{} + if err := util.Convert(right, c); err != nil { + if returnErr { + return nil, err + } + log.Errorf("Failed to parse config file %s: %s", file, err) + continue } left = util.Merge(left, right) } - if bytes != nil && len(bytes) > 0 { - right := make(map[interface{}]interface{}) - if substituteMetadataVars { - bytes = substituteVars(bytes, metadata) - } - if err := yaml.Unmarshal(bytes, &right); err != nil { - return nil, err - } - - left = util.Merge(left, right) + if bytes == nil || len(bytes) == 0 { + return left, nil } + right := make(map[interface{}]interface{}) + if substituteMetadataVars { + bytes = substituteVars(bytes, metadata) + } + + if err := yaml.Unmarshal(bytes, &right); err != nil { + if returnErr { + return nil, err + } + log.Errorf("Failed to parse bytes: %s", err) + return left, nil + } + + c := &CloudConfig{} + if err := util.Convert(right, c); err != nil { + if returnErr { + return nil, err + } + log.Errorf("Failed to parse bytes: %s", err) + return left, nil + } + + left = util.Merge(left, right) return left, nil } diff --git a/docker/service.go b/docker/service.go index 0975de9d..7a58b6fc 100644 --- a/docker/service.go +++ b/docker/service.go @@ -80,10 +80,7 @@ func (s *Service) shouldRebuild(ctx context.Context) (bool, error) { if err != nil { return false, err } - cfg, err := config.LoadConfig() - if err != nil { - return false, err - } + cfg := config.LoadConfig() for _, c := range containers { outOfSync, err := c.(*docker.Container).OutOfSync(ctx, s.Service.Config().Image) if err != nil { diff --git a/init/init.go b/init/init.go index 598829be..a2318c36 100644 --- a/init/init.go +++ b/init/init.go @@ -117,10 +117,7 @@ func mountState(cfg *config.CloudConfig) error { func mountOem(cfg *config.CloudConfig) (*config.CloudConfig, error) { if cfg == nil { - var err error - if cfg, err = config.LoadConfig(); err != nil { - return cfg, err - } + cfg = config.LoadConfig() } if err := mountConfigured("oem", cfg.Rancher.State.OemDev, cfg.Rancher.State.OemFsType, config.OEM); err != nil { log.Debugf("Not mounting OEM: %v", err) @@ -198,10 +195,7 @@ func RunInit() error { }, mountOem, func(_ *config.CloudConfig) (*config.CloudConfig, error) { - cfg, err := config.LoadConfig() - if err != nil { - return cfg, err - } + cfg := config.LoadConfig() if cfg.Rancher.Debug { cfgString, err := config.Export(false, true) @@ -217,7 +211,7 @@ func RunInit() error { loadModules, tryMountAndBootstrap, func(_ *config.CloudConfig) (*config.CloudConfig, error) { - return config.LoadConfig() + return config.LoadConfig(), nil }, loadModules, func(c *config.CloudConfig) (*config.CloudConfig, error) { diff --git a/init/sysinit.go b/init/sysinit.go index bf6f3f84..cd7a1008 100644 --- a/init/sysinit.go +++ b/init/sysinit.go @@ -89,12 +89,9 @@ func loadImages(cfg *config.CloudConfig) (*config.CloudConfig, error) { } func SysInit() error { - cfg, err := config.LoadConfig() - if err != nil { - return err - } + cfg := config.LoadConfig() - _, err = config.ChainCfgFuncs(cfg, + _, err := config.ChainCfgFuncs(cfg, loadImages, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { p, err := compose.GetProject(cfg, false)