diff --git a/internal/cmd/config/list/list.go b/internal/cmd/config/list/list.go index b6bdf48e2..0f6974703 100644 --- a/internal/cmd/config/list/list.go +++ b/internal/cmd/config/list/list.go @@ -37,11 +37,6 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit config list"), ), RunE: func(cmd *cobra.Command, args []string) error { - err := viper.ReadInConfig() - if err != nil { - return fmt.Errorf("read config file: %w", err) - } - configData := viper.AllSettings() // Sort the config options by key @@ -84,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { table.AddRow(key, valueString) table.AddSeparator() } - err = table.Display(p) + err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) } diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 36e9c06d4..459f3a3b4 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -80,9 +80,9 @@ func NewCmd(p *print.Printer) *cobra.Command { viper.Set(config.ProjectNameKey, "") } - err = viper.WriteConfig() + err = config.Write() if err != nil { - return fmt.Errorf("write new config to file: %w", err) + return fmt.Errorf("write config to file: %w", err) } return nil }, diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index ff4e4d665..7f6bc8449 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -144,9 +144,9 @@ func NewCmd() *cobra.Command { viper.Set(config.SKECustomEndpointKey, "") } - err := viper.WriteConfig() + err := config.Write() if err != nil { - return fmt.Errorf("write updated config to file: %w", err) + return fmt.Errorf("write config to file: %w", err) } return nil }, diff --git a/internal/pkg/auth/storage.go b/internal/pkg/auth/storage.go index 3a2031fff..1bcb6e784 100644 --- a/internal/pkg/auth/storage.go +++ b/internal/pkg/auth/storage.go @@ -136,7 +136,7 @@ func GetAuthField(key authFieldKey) (string, error) { var errFallback error value, errFallback = getAuthFieldFromEncodedTextFile(key) if errFallback != nil { - return "", fmt.Errorf("write to keyring failed (%w), tried write to encoded text file: %w", err, errFallback) + return "", fmt.Errorf("read from keyring: %w, read from encoded file as fallback: %w", err, errFallback) } } return value, nil diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 08eac0b98..4077c1d3a 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -70,30 +70,42 @@ var ConfigKeys = []string{ SKECustomEndpointKey, } +var folderPath string + func InitConfig() { home, err := os.UserHomeDir() cobra.CheckErr(err) configFolderPath := filepath.Join(home, configFolder) configFilePath := filepath.Join(configFolderPath, fmt.Sprintf("%s.%s", configFileName, configFileExtension)) - viper.SetConfigName(configFileName) - viper.SetConfigType(configFileExtension) - viper.AddConfigPath(configFolderPath) + // Write config dir path to global variable + folderPath = configFolderPath - err = createFolderIfNotExists(configFolderPath) - cobra.CheckErr(err) - err = createFileIfNotExists(configFilePath) - cobra.CheckErr(err) + // This hack is required to allow creating the config file with `viper.WriteConfig` + // see https://github.com/spf13/viper/issues/851#issuecomment-789393451 + viper.SetConfigFile(configFilePath) + + f, err := os.Open(configFilePath) + if !os.IsNotExist(err) { + if err := viper.ReadConfig(f); err != nil { + cobra.CheckErr(err) + } + } + defer func() { + if f != nil { + if err := f.Close(); err != nil { + cobra.CheckErr(err) + } + } + }() - err = viper.ReadInConfig() - cobra.CheckErr(err) setConfigDefaults() viper.AutomaticEnv() viper.SetEnvPrefix("stackit") } -func createFolderIfNotExists(folderPath string) error { +func createFolderIfNotExists() error { _, err := os.Stat(folderPath) if os.IsNotExist(err) { err := os.MkdirAll(folderPath, os.ModePerm) @@ -106,17 +118,12 @@ func createFolderIfNotExists(folderPath string) error { return nil } -func createFileIfNotExists(filePath string) error { - _, err := os.Stat(filePath) - if os.IsNotExist(err) { - err := viper.SafeWriteConfigAs(filePath) - if err != nil { - return err - } - } else if err != nil { - return err +// Write saves the config file (wrapping `viper.WriteConfig`) and ensures that its directory exists +func Write() error { + if err := createFolderIfNotExists(); err != nil { + return fmt.Errorf("create config directory: %w", err) } - return nil + return viper.WriteConfig() } // All config keys should be set to a default value so that they can be set as an environment variable diff --git a/internal/pkg/projectname/project_name.go b/internal/pkg/projectname/project_name.go index d2a54ff0a..9f80da8ab 100644 --- a/internal/pkg/projectname/project_name.go +++ b/internal/pkg/projectname/project_name.go @@ -43,7 +43,7 @@ func GetProjectName(ctx context.Context, cmd *cobra.Command, p *print.Printer) ( // (So next time we can just pull it from there) if !isProjectIdSetInFlags(cmd) { viper.Set(config.ProjectNameKey, projectName) - err = viper.WriteConfig() + err = config.Write() if err != nil { return "", fmt.Errorf("write new config to file: %w", err) }