Add --overwrite option to config init cmd

Currently airshipctl will overwrite an existing config file
by default during config init execution. This patch adds an
appropriate flag to explicitly control whether the user wants
to overwrite an existing file or not.

Change-Id: I9f4756b98e9d1245145809aed203974e99feb662
Signed-off-by: Ruslan Aliev <raliev@mirantis.com>
This commit is contained in:
Ruslan Aliev 2020-10-07 17:36:01 -05:00 committed by Kostyantyn Kalynovskyi
parent 3561c28862
commit f7217245a7
10 changed files with 91 additions and 41 deletions

View File

@ -22,34 +22,41 @@ import (
const ( const (
initLong = ` initLong = `
Generate an airshipctl config file and its associated kubeConfig file. Generate an airshipctl config file. This file by default will be written to the $HOME/.airship directory,
These files will be written to the $HOME/.airship directory, and will contain and will contain default configuration. In case if flag --airshipconf provided - the file will be
default configurations. 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 { func NewInitCommand() *cobra.Command {
// TODO(howell): It'd be nice to have a flag to tell var overwrite bool
// 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.
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "init", Use: "init",
Short: "Generate initial configuration files for airshipctl", Short: "Generate initial configuration file for airshipctl",
Long: initLong[1:], Long: initLong[1:],
Example: initExample,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
airshipConfigPath, err := cmd.Flags().GetString("airshipconf") airshipConfigPath, err := cmd.Flags().GetString("airshipconf")
if err != nil { if err != nil {
airshipConfigPath = "" airshipConfigPath = ""
} }
return config.CreateConfig(airshipConfigPath) return config.CreateConfig(airshipConfigPath, overwrite)
}, },
} }
cmd.Flags().BoolVar(&overwrite, "overwrite", false, "overwrite config file")
return cmd return cmd
} }

View File

@ -92,7 +92,7 @@ func NewSetManagementConfigCommand(cfgFactory config.Factory) *cobra.Command {
return nil return nil
} }
return cfg.PersistConfig() return cfg.PersistConfig(true)
}, },
} }

View File

@ -9,7 +9,7 @@ Available Commands:
get-management-config View a management config or all management configs defined in the airshipctl config 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 get-manifest Get a manifest information from the airshipctl config
help Help about any command help Help about any command
init Generate initial configuration files for airshipctl init Generate initial configuration file for airshipctl
set-context Manage contexts set-context Manage contexts
set-encryption-config Manage encryption configs in airship config set-encryption-config Manage encryption configs in airship config
set-management-config Modify an out-of-band management configuration set-management-config Modify an out-of-band management configuration

View File

@ -1,11 +1,23 @@
Generate an airshipctl config file and its associated kubeConfig file. Generate an airshipctl config file. This file by default will be written to the $HOME/.airship directory,
These files will be written to the $HOME/.airship directory, and will contain and will contain default configuration. In case if flag --airshipconf provided - the file will be
default configurations. 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.
NOTE: This will overwrite any existing config files in $HOME/.airship
Usage: Usage:
init [flags] 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: Flags:
-h, --help help for init -h, --help help for init
--overwrite overwrite config file

View File

@ -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-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-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 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-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-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 * [airshipctl config set-management-config](airshipctl_config_set-management-config.md) - Modify an out-of-band management configuration

View File

@ -1,24 +1,39 @@
## airshipctl config init ## airshipctl config init
Generate initial configuration files for airshipctl Generate initial configuration file for airshipctl
### Synopsis ### Synopsis
Generate an airshipctl config file and its associated kubeConfig file. Generate an airshipctl config file. This file by default will be written to the $HOME/.airship directory,
These files will be written to the $HOME/.airship directory, and will contain and will contain default configuration. In case if flag --airshipconf provided - the file will be
default configurations. 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.
NOTE: This will overwrite any existing config files in $HOME/.airship
``` ```
airshipctl config init [flags] 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 ### Options
``` ```
-h, --help help for init -h, --help help for init
--overwrite overwrite config file
``` ```
### Options inherited from parent commands ### Options inherited from parent commands

View File

@ -94,11 +94,11 @@ func CreateFactory(airshipConfigPath *string) Factory {
} }
} }
// CreateConfig saves default config to specified paths // CreateConfig saves default config to the specified path
func CreateConfig(airshipConfigPath string) error { func CreateConfig(airshipConfigPath string, overwrite bool) error {
cfg := NewConfig() cfg := NewConfig()
cfg.initConfigPath(airshipConfigPath) cfg.initConfigPath(airshipConfigPath)
return cfg.PersistConfig() return cfg.PersistConfig(overwrite)
} }
// initConfigPath - Initializes loadedConfigPath variable for Config object // initConfigPath - Initializes loadedConfigPath variable for Config object
@ -177,8 +177,12 @@ func (c *Config) EnsureComplete() error {
// PersistConfig updates the airshipctl config file to match // PersistConfig updates the airshipctl config file to match
// the current Config object. // the current Config object.
// If file did not previously exist, the file will be created. // If file did not previously exist, the file will be created.
// Otherwise, the file will be overwritten // The file will be overwritten if overwrite argument set to true
func (c *Config) PersistConfig() error { 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() airshipConfigYaml, err := c.ToYaml()
if err != nil { if err != nil {
return err return err

View File

@ -60,7 +60,7 @@ func RunSetContext(o *ContextOptions, airconfig *Config, writeToStorage bool) (b
} }
// Update configuration file just in time persistence approach // Update configuration file just in time persistence approach
if writeToStorage { if writeToStorage {
if err := airconfig.PersistConfig(); err != nil { if err := airconfig.PersistConfig(true); err != nil {
// Error that it didnt persist the changes // Error that it didnt persist the changes
return modified, ErrConfigFailed{} return modified, ErrConfigFailed{}
} }
@ -77,7 +77,7 @@ func RunUseContext(desiredContext string, airconfig *Config) error {
if airconfig.CurrentContext != desiredContext { if airconfig.CurrentContext != desiredContext {
airconfig.CurrentContext = desiredContext airconfig.CurrentContext = desiredContext
if err := airconfig.PersistConfig(); err != nil { if err := airconfig.PersistConfig(true); err != nil {
return err return err
} }
} }
@ -107,7 +107,7 @@ func RunSetManifest(o *ManifestOptions, airconfig *Config, writeToStorage bool)
} }
// Update configuration file just in time persistence approach // Update configuration file just in time persistence approach
if writeToStorage { if writeToStorage {
if err := airconfig.PersistConfig(); err != nil { if err := airconfig.PersistConfig(true); err != nil {
// Error that it didnt persist the changes // Error that it didnt persist the changes
return modified, ErrConfigFailed{} return modified, ErrConfigFailed{}
} }
@ -138,7 +138,7 @@ func RunSetEncryptionConfig(o *EncryptionConfigOptions, airconfig *Config, write
} }
// Update configuration file just in time persistence approach // Update configuration file just in time persistence approach
if writeToStorage { if writeToStorage {
if err := airconfig.PersistConfig(); err != nil { if err := airconfig.PersistConfig(true); err != nil {
// Error that it didnt persist the changes // Error that it didnt persist the changes
return modified, ErrConfigFailed{} return modified, ErrConfigFailed{}
} }

View File

@ -101,11 +101,14 @@ func TestPersistConfig(t *testing.T) {
conf.SetLoadedConfigPath(conf.LoadedConfigPath() + ".new") conf.SetLoadedConfigPath(conf.LoadedConfigPath() + ".new")
err := conf.PersistConfig() err := conf.PersistConfig(true)
require.NoError(t, err) require.NoError(t, err)
// Check that the files were created // Check that the files were created
assert.FileExists(t, conf.LoadedConfigPath()) assert.FileExists(t, conf.LoadedConfigPath())
err = conf.PersistConfig(false)
require.Error(t, err, config.ErrConfigFileExists{Path: conf.LoadedConfigPath()})
} }
func TestEnsureComplete(t *testing.T) { func TestEnsureComplete(t *testing.T) {
@ -206,7 +209,7 @@ func TestPurge(t *testing.T) {
defer cleanup(t) defer cleanup(t)
// Store it // Store it
err := conf.PersistConfig() err := conf.PersistConfig(true)
assert.NoErrorf(t, err, "Unable to persist configuration expected at %v", conf.LoadedConfigPath()) assert.NoErrorf(t, err, "Unable to persist configuration expected at %v", conf.LoadedConfigPath())
// Verify that the file is there // Verify that the file is there

View File

@ -305,3 +305,12 @@ type ErrCheckFile struct {
func (e ErrCheckFile) Error() string { func (e ErrCheckFile) Error() string {
return fmt.Sprintf("could not read %s data from '%s': %v", e.FlagName, e.Path, e.InternalErr) 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)
}