From a46992d460c55dc923ecd667d258ebaa19e26d64 Mon Sep 17 00:00:00 2001 From: Mark D Horn Date: Tue, 19 Nov 2019 15:57:50 -0800 Subject: [PATCH] model: Refactor to enable command line overrides Enable conversion from JSON to YAML to have values overridden by the command line arguments. Signed-off-by: Mark D Horn --- clr-installer/main.go | 47 +++++++++++++++++----------- model/model_ister.go | 71 +++++++++++++++++++++++++++---------------- model/model_test.go | 13 ++++++-- 3 files changed, 84 insertions(+), 47 deletions(-) diff --git a/clr-installer/main.go b/clr-installer/main.go index c98d4b7..e8f6266 100644 --- a/clr-installer/main.go +++ b/clr-installer/main.go @@ -152,22 +152,6 @@ func execute(options args.Args) error { return nil } - if options.ConvertConfigFile != "" && options.TemplateConfigFile != "" { - return errors.Errorf("Options --json-yaml and --template are mutually exclusive.") - } - - if options.ConvertConfigFile != "" { - if filepath.Ext(options.ConvertConfigFile) == ".json" { - _, err := model.JSONtoYAMLConfig(options.ConvertConfigFile) - if err != nil { - return err - } - } else { - return errors.Errorf("Config file '%s' must end in '.json'", options.ConvertConfigFile) - } - return nil - } - var md *model.SystemInstall cf := options.ConfigFile @@ -190,7 +174,11 @@ func execute(options args.Args) error { } if filepath.Ext(cf) == ".json" { - cf, err = model.JSONtoYAMLConfig(cf) + _, err = model.JSONtoYAMLConfig(cf) + if err != nil { + return err + } + cf, err = md.WriteYAMLConfig(cf) if err != nil { return err } @@ -202,6 +190,22 @@ func execute(options args.Args) error { } md.ClearInstallSelected() + if options.ConvertConfigFile != "" && options.TemplateConfigFile != "" { + return errors.Errorf("Options --json-yaml and --template are mutually exclusive.") + } + + if options.ConvertConfigFile != "" { + var err error + if filepath.Ext(options.ConvertConfigFile) == ".json" { + md, err = model.JSONtoYAMLConfig(options.ConvertConfigFile) + if err != nil { + return err + } + } else { + return errors.Errorf("Config file '%s' must end in '.json'", options.ConvertConfigFile) + } + } + if options.CfPurgeSet && options.CfPurge { defer func() { _ = os.Remove(cf) }() md.ClearCfFile = cf @@ -278,6 +282,15 @@ func execute(options args.Args) error { log.Info("Overriding bundle list from command line: %s", strings.Join(md.Bundles, ", ")) } + if options.ConvertConfigFile != "" { + _, err := md.WriteYAMLConfig(options.ConvertConfigFile) + if err != nil { + return err + } + + return nil + } + if options.TemplateConfigFile != "" { if filepath.Ext(options.TemplateConfigFile) == ".yaml" { md.StorageAlias = append(md.StorageAlias, &model.StorageAlias{Name: "release", File: "release.img"}) diff --git a/model/model_ister.go b/model/model_ister.go index 54e13bb..1134553 100644 --- a/model/model_ister.go +++ b/model/model_ister.go @@ -85,12 +85,14 @@ type Network struct { DNS string `json:"dns"` } -// JSONtoYAMLConfig converts the "ister"JSON config to the corresponding YAML config fields -// and writes it out to a YAML config file. -func JSONtoYAMLConfig(cf string) (string, error) { +// JSONtoYAMLConfig converts the "ister" JSON config to the corresponding +// YAML config fields and return the model +func JSONtoYAMLConfig(cf string) (*SystemInstall, error) { + var si SystemInstall + fp, err := os.Open(cf) if err != nil { - return cf, errors.Wrap(err) + return nil, errors.Wrap(err) } log.Debug("Successfully opened config file: %s", cf) defer func() { @@ -99,17 +101,15 @@ func JSONtoYAMLConfig(cf string) (string, error) { b, err := ioutil.ReadAll(fp) if err != nil { - return cf, errors.Wrap(err) + return nil, errors.Wrap(err) } ic := IsterConfig{} err = json.Unmarshal(b, &ic) if err != nil { - return cf, errors.Wrap(err) + return nil, errors.Wrap(err) } - si := SystemInstall{} - var disks = make(map[string](map[uint64]storage.BlockDevice)) // Key: Disk name, Value: Map of Partitions // For each partition, set the Size @@ -131,7 +131,7 @@ func JSONtoYAMLConfig(cf string) (string, error) { sa.Name = strings.TrimSuffix(curr.Disk, filepath.Ext(curr.Disk)) // remove any extensions from alias name sa.File = "/dev/" + curr.Disk default: - return cf, errors.Errorf("invalid DestinationType in config file %s", cf) + return nil, errors.Errorf("invalid DestinationType in config file %s", cf) } si.StorageAlias = append(si.StorageAlias, &sa) si.AddTargetMedia(&bd) @@ -139,17 +139,17 @@ func JSONtoYAMLConfig(cf string) (string, error) { var partitions = make(map[uint64]storage.BlockDevice) partitions[curr.Partition], err = setStorageValues(curr.Disk, curr.Partition, curr.Size) if err != nil { - return cf, errors.Wrap(err) + return nil, errors.Wrap(err) } disks[curr.Disk] = partitions } else { _, ok := partitions[curr.Partition] if ok { - return cf, fmt.Errorf("partition %d already defined for disk %s in config file %s", curr.Partition, curr.Disk, cf) + return nil, fmt.Errorf("partition %d already defined for disk %s in config file %s", curr.Partition, curr.Disk, cf) } partitions[curr.Partition], err = setStorageValues(curr.Disk, curr.Partition, curr.Size) if err != nil { - return cf, errors.Wrap(err) + return nil, errors.Wrap(err) } disks[curr.Disk] = partitions } @@ -159,12 +159,12 @@ func JSONtoYAMLConfig(cf string) (string, error) { for _, curr := range ic.FilesystemTypes { partitions, ok := disks[curr.Disk] if !ok { - return cf, errors.Errorf("disk %s not defined in config file %s", curr.Disk, cf) + return nil, errors.Errorf("disk %s not defined in config file %s", curr.Disk, cf) } part, ok := partitions[curr.Partition] if !ok { - return cf, errors.Errorf("partition %d not defined for disk %s in config file %s", curr.Partition, curr.Disk, cf) + return nil, errors.Errorf("partition %d not defined for disk %s in config file %s", curr.Partition, curr.Disk, cf) } part.FsType = curr.Type part.Options = curr.Options @@ -177,12 +177,12 @@ func JSONtoYAMLConfig(cf string) (string, error) { for _, curr := range ic.PartitionMountPoints { partitions, ok := disks[curr.Disk] if !ok { - return cf, errors.Errorf("disk %s not defined in config file %s", curr.Disk, cf) + return nil, errors.Errorf("disk %s not defined in config file %s", curr.Disk, cf) } part, ok := partitions[curr.Partition] if !ok { - return cf, errors.Errorf("partition %d not defined for partitions %s in config file %s", curr.Partition, curr.Disk, cf) + return nil, errors.Errorf("partition %d not defined for partitions %s in config file %s", curr.Partition, curr.Disk, cf) } part.MountPoint = curr.Mount @@ -271,11 +271,13 @@ func JSONtoYAMLConfig(cf string) (string, error) { si.HTTPSProxy = ic.HTTPSProxy // Set HTTPSProxy if si.HTTPSProxy == "" { si.HTTPSProxy = ic.HTTPProxy - fmt.Println("WARNING: Mapping HTTPProxy in json to HTTPSProxy in yaml") - log.Warning("Mapping HTTPProxy in json to HTTPSProxy in yaml") + msg := fmt.Sprint("Mapping HTTPProxy in json to HTTPSProxy in yaml") + fmt.Println("WARNING: " + msg) + log.Warning(msg) } else { - fmt.Println("WARNING: Skipping HTTPProxy mapping") - log.Warning("Skipping HTTPProxy mapping") + msg := fmt.Sprint("Skipping HTTPProxy mapping") + fmt.Println("WARNING: " + msg) + log.Warning(msg) } // Hardcoding the missing required fields @@ -285,11 +287,22 @@ func JSONtoYAMLConfig(cf string) (string, error) { si.Language = &language.Language{Code: language.DefaultLanguage} // Set Language if ic.VersionURL != "" { - fmt.Println("WARNING: Skipping VersionURL mapping as it not supported in clr-installer config") - log.Warning("Skipping VersionURL mapping as it not supported in clr-installer config") + msg := fmt.Sprint("Skipping VersionURL mapping as it not supported in clr-installer config") + fmt.Println("WARNING: " + msg) + log.Warning(msg) + } + + return &si, nil +} + +// WriteYAMLConfig writes out the current model to a configuration file +// If the config file ends in JSON, it renames it to YAML +// If the file exists, it first makes a backup +func (si *SystemInstall) WriteYAMLConfig(cf string) (string, error) { + if filepath.Ext(cf) == ".json" { + cf = strings.TrimSuffix(cf, filepath.Ext(cf)) + ".yaml" } - cf = strings.TrimSuffix(cf, filepath.Ext(cf)) + ".yaml" info, err := os.Stat(cf) if err != nil { if os.IsNotExist(err) { @@ -307,16 +320,20 @@ func JSONtoYAMLConfig(cf string) (string, error) { if err != nil { return cf, errors.Wrap(err) } - fmt.Printf("WARNING: Config file %s already exists. Making a backup: %s\n", cf, bf) - log.Warning("Config file %s already exists. Taking a backup: %s\n", cf, bf) + msg := fmt.Sprintf("Config file %s already exists. Making a backup: %s", cf, bf) + fmt.Println("WARNING: " + msg) + log.Warning(msg) } err = si.WriteFile(cf) if err != nil { return cf, errors.Wrap(err) } - fmt.Println("Converted config file from JSON to YAML: " + cf) - log.Info("Converted config file from JSON to YAML: " + cf) + + msg := fmt.Sprint("Converted config file from JSON to YAML: " + cf) + fmt.Println(msg) + log.Info(msg) + return cf, nil } diff --git a/model/model_test.go b/model/model_test.go index 0a729d8..e3a5c16 100644 --- a/model/model_test.go +++ b/model/model_test.go @@ -94,9 +94,12 @@ func TestLoadFile(t *testing.T) { for _, curr := range tests { path := filepath.Join(testsDir, curr.file) - var err error if filepath.Ext(curr.file) == ".json" { - path, err = JSONtoYAMLConfig(path) + md, err := JSONtoYAMLConfig(path) + if err == nil { + path, err = md.WriteYAMLConfig(path) + } + if curr.valid && err != nil { t.Fatalf("%s is a valid test and shouldn't return an error: %v", curr.file, err) } @@ -570,7 +573,11 @@ func TestBackupFile(t *testing.T) { mt.Hour(), mt.Minute(), mt.Second()) bf := strings.TrimSuffix(cf, filepath.Ext(cf)) + suffix + ".yaml" - path, err = JSONtoYAMLConfig(path) + md, err := JSONtoYAMLConfig(path) + if err == nil { + path, err = md.WriteYAMLConfig(path) + } + if err != nil { t.Fatalf("%s is a valid test and shouldn't return an error: %v", path, err) }