diff --git a/cmd/config/init.go b/cmd/config/init.go index d746fecdc..ef950b70a 100644 --- a/cmd/config/init.go +++ b/cmd/config/init.go @@ -22,34 +22,41 @@ import ( const ( initLong = ` -Generate an airshipctl config file and its associated kubeConfig file. -These files will be written to the $HOME/.airship directory, and will contain -default configurations. +Generate an airshipctl config file. This file by default will be written to the $HOME/.airship directory, +and will contain default configuration. In case if flag --airshipconf provided - the file will be +written to the specified location instead. If a configuration file already exists at the specified path, +an error will be thrown; to overwrite it, specify the --overwrite flag. +` + initExample = ` +# Create new airshipctl config file at the default location +airshipctl config init -NOTE: This will overwrite any existing config files in $HOME/.airship +# Create new airshipctl config file at the custom location +airshipctl config init --airshipconf path/to/config + +# Create new airshipctl config file at custom location and overwrite it +airshipctl config init --overwrite --airshipconf path/to/config ` ) -// NewInitCommand creates a command for generating default airshipctl config files. +// NewInitCommand creates a command for generating default airshipctl config file. func NewInitCommand() *cobra.Command { - // TODO(howell): It'd be nice to have a flag to tell - // airshipctl where to store the new files. - // TODO(howell): Currently, this command overwrites whatever the user - // has in their airship directory. We should remove that functionality - // as default and provide and optional --overwrite flag. + var overwrite bool cmd := &cobra.Command{ - Use: "init", - Short: "Generate initial configuration files for airshipctl", - Long: initLong[1:], + Use: "init", + Short: "Generate initial configuration file for airshipctl", + Long: initLong[1:], + Example: initExample, RunE: func(cmd *cobra.Command, args []string) error { airshipConfigPath, err := cmd.Flags().GetString("airshipconf") if err != nil { airshipConfigPath = "" } - return config.CreateConfig(airshipConfigPath) + return config.CreateConfig(airshipConfigPath, overwrite) }, } + cmd.Flags().BoolVar(&overwrite, "overwrite", false, "overwrite config file") return cmd } diff --git a/cmd/config/set_management_configuration.go b/cmd/config/set_management_configuration.go index 82a899ba7..bcca48a2e 100644 --- a/cmd/config/set_management_configuration.go +++ b/cmd/config/set_management_configuration.go @@ -92,7 +92,7 @@ func NewSetManagementConfigCommand(cfgFactory config.Factory) *cobra.Command { return nil } - return cfg.PersistConfig() + return cfg.PersistConfig(true) }, } diff --git a/cmd/config/testdata/TestConfigGoldenOutput/config-cmd-with-help.golden b/cmd/config/testdata/TestConfigGoldenOutput/config-cmd-with-help.golden index 6912569ee..53de3049f 100644 --- a/cmd/config/testdata/TestConfigGoldenOutput/config-cmd-with-help.golden +++ b/cmd/config/testdata/TestConfigGoldenOutput/config-cmd-with-help.golden @@ -9,7 +9,7 @@ Available Commands: get-management-config View a management config or all management configs defined in the airshipctl config get-manifest Get a manifest information from the airshipctl config help Help about any command - init Generate initial configuration files for airshipctl + init Generate initial configuration file for airshipctl set-context Manage contexts set-encryption-config Manage encryption configs in airship config set-management-config Modify an out-of-band management configuration diff --git a/cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden b/cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden index fcc51693f..e3ed66334 100644 --- a/cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden +++ b/cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden @@ -1,11 +1,23 @@ -Generate an airshipctl config file and its associated kubeConfig file. -These files will be written to the $HOME/.airship directory, and will contain -default configurations. - -NOTE: This will overwrite any existing config files in $HOME/.airship +Generate an airshipctl config file. This file by default will be written to the $HOME/.airship directory, +and will contain default configuration. In case if flag --airshipconf provided - the file will be +written to the specified location instead. If a configuration file already exists at the specified path, +an error will be thrown; to overwrite it, specify the --overwrite flag. Usage: init [flags] +Examples: + +# Create new airshipctl config file at the default location +airshipctl config init + +# Create new airshipctl config file at the custom location +airshipctl config init --airshipconf path/to/config + +# Create new airshipctl config file at custom location and overwrite it +airshipctl config init --overwrite --airshipconf path/to/config + + Flags: - -h, --help help for init + -h, --help help for init + --overwrite overwrite config file diff --git a/docs/source/cli/airshipctl_config.md b/docs/source/cli/airshipctl_config.md index 23e06f4d1..f40149c59 100644 --- a/docs/source/cli/airshipctl_config.md +++ b/docs/source/cli/airshipctl_config.md @@ -26,7 +26,7 @@ Manage the airshipctl config file * [airshipctl config get-encryption-config](airshipctl_config_get-encryption-config.md) - Get an encryption config information from the airshipctl config * [airshipctl config get-management-config](airshipctl_config_get-management-config.md) - View a management config or all management configs defined in the airshipctl config * [airshipctl config get-manifest](airshipctl_config_get-manifest.md) - Get a manifest information from the airshipctl config -* [airshipctl config init](airshipctl_config_init.md) - Generate initial configuration files for airshipctl +* [airshipctl config init](airshipctl_config_init.md) - Generate initial configuration file for airshipctl * [airshipctl config set-context](airshipctl_config_set-context.md) - Manage contexts * [airshipctl config set-encryption-config](airshipctl_config_set-encryption-config.md) - Manage encryption configs in airship config * [airshipctl config set-management-config](airshipctl_config_set-management-config.md) - Modify an out-of-band management configuration diff --git a/docs/source/cli/airshipctl_config_init.md b/docs/source/cli/airshipctl_config_init.md index 44fff0ca5..fbdbd0223 100644 --- a/docs/source/cli/airshipctl_config_init.md +++ b/docs/source/cli/airshipctl_config_init.md @@ -1,24 +1,39 @@ ## airshipctl config init -Generate initial configuration files for airshipctl +Generate initial configuration file for airshipctl ### Synopsis -Generate an airshipctl config file and its associated kubeConfig file. -These files will be written to the $HOME/.airship directory, and will contain -default configurations. - -NOTE: This will overwrite any existing config files in $HOME/.airship +Generate an airshipctl config file. This file by default will be written to the $HOME/.airship directory, +and will contain default configuration. In case if flag --airshipconf provided - the file will be +written to the specified location instead. If a configuration file already exists at the specified path, +an error will be thrown; to overwrite it, specify the --overwrite flag. ``` airshipctl config init [flags] ``` +### Examples + +``` + +# Create new airshipctl config file at the default location +airshipctl config init + +# Create new airshipctl config file at the custom location +airshipctl config init --airshipconf path/to/config + +# Create new airshipctl config file at custom location and overwrite it +airshipctl config init --overwrite --airshipconf path/to/config + +``` + ### Options ``` - -h, --help help for init + -h, --help help for init + --overwrite overwrite config file ``` ### Options inherited from parent commands diff --git a/pkg/config/config.go b/pkg/config/config.go index f3f599eb0..1f8f9297b 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -94,11 +94,11 @@ func CreateFactory(airshipConfigPath *string) Factory { } } -// CreateConfig saves default config to specified paths -func CreateConfig(airshipConfigPath string) error { +// CreateConfig saves default config to the specified path +func CreateConfig(airshipConfigPath string, overwrite bool) error { cfg := NewConfig() cfg.initConfigPath(airshipConfigPath) - return cfg.PersistConfig() + return cfg.PersistConfig(overwrite) } // initConfigPath - Initializes loadedConfigPath variable for Config object @@ -177,8 +177,12 @@ func (c *Config) EnsureComplete() error { // PersistConfig updates the airshipctl config file to match // the current Config object. // If file did not previously exist, the file will be created. -// Otherwise, the file will be overwritten -func (c *Config) PersistConfig() error { +// The file will be overwritten if overwrite argument set to true +func (c *Config) PersistConfig(overwrite bool) error { + if _, err := os.Stat(c.loadedConfigPath); err == nil && !overwrite { + return ErrConfigFileExists{Path: c.loadedConfigPath} + } + airshipConfigYaml, err := c.ToYaml() if err != nil { return err diff --git a/pkg/config/config_helper.go b/pkg/config/config_helper.go index 8b9de108f..9803a5f7d 100644 --- a/pkg/config/config_helper.go +++ b/pkg/config/config_helper.go @@ -60,7 +60,7 @@ func RunSetContext(o *ContextOptions, airconfig *Config, writeToStorage bool) (b } // Update configuration file just in time persistence approach if writeToStorage { - if err := airconfig.PersistConfig(); err != nil { + if err := airconfig.PersistConfig(true); err != nil { // Error that it didnt persist the changes return modified, ErrConfigFailed{} } @@ -77,7 +77,7 @@ func RunUseContext(desiredContext string, airconfig *Config) error { if airconfig.CurrentContext != desiredContext { airconfig.CurrentContext = desiredContext - if err := airconfig.PersistConfig(); err != nil { + if err := airconfig.PersistConfig(true); err != nil { return err } } @@ -107,7 +107,7 @@ func RunSetManifest(o *ManifestOptions, airconfig *Config, writeToStorage bool) } // Update configuration file just in time persistence approach if writeToStorage { - if err := airconfig.PersistConfig(); err != nil { + if err := airconfig.PersistConfig(true); err != nil { // Error that it didnt persist the changes return modified, ErrConfigFailed{} } @@ -138,7 +138,7 @@ func RunSetEncryptionConfig(o *EncryptionConfigOptions, airconfig *Config, write } // Update configuration file just in time persistence approach if writeToStorage { - if err := airconfig.PersistConfig(); err != nil { + if err := airconfig.PersistConfig(true); err != nil { // Error that it didnt persist the changes return modified, ErrConfigFailed{} } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 93bf74656..97711f000 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -101,11 +101,14 @@ func TestPersistConfig(t *testing.T) { conf.SetLoadedConfigPath(conf.LoadedConfigPath() + ".new") - err := conf.PersistConfig() + err := conf.PersistConfig(true) require.NoError(t, err) // Check that the files were created assert.FileExists(t, conf.LoadedConfigPath()) + + err = conf.PersistConfig(false) + require.Error(t, err, config.ErrConfigFileExists{Path: conf.LoadedConfigPath()}) } func TestEnsureComplete(t *testing.T) { @@ -206,7 +209,7 @@ func TestPurge(t *testing.T) { defer cleanup(t) // Store it - err := conf.PersistConfig() + err := conf.PersistConfig(true) assert.NoErrorf(t, err, "Unable to persist configuration expected at %v", conf.LoadedConfigPath()) // Verify that the file is there diff --git a/pkg/config/errors.go b/pkg/config/errors.go index 641510935..1b63a6cc4 100644 --- a/pkg/config/errors.go +++ b/pkg/config/errors.go @@ -305,3 +305,12 @@ type ErrCheckFile struct { func (e ErrCheckFile) Error() string { return fmt.Sprintf("could not read %s data from '%s': %v", e.FlagName, e.Path, e.InternalErr) } + +// ErrConfigFileExists is returned when there is an existing file at specified location +type ErrConfigFileExists struct { + Path string +} + +func (e ErrConfigFileExists) Error() string { + return fmt.Sprintf("could not create default config at %s, file already exists", e.Path) +}