Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions cmd/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ var configureCmd = &cobra.Command{

대화형 모드:
solactl configure
solactl configure --profile staging

비대화형 모드:
solactl configure --api-key <key> --api-secret <secret>
solactl configure --profile staging --api-key <key> --api-secret <secret>

API Key는 https://console.solapi.com 에서 발급받을 수 있습니다.`,
RunE: runConfigure,
Expand All @@ -34,20 +36,27 @@ func runConfigure(cmd *cobra.Command, args []string) error {
apiKey := flagAPIKey
apiSecret := flagAPISecret

// Determine target profile name
profileName := flagProfile
if profileName == "" {
profileName, _ = config.ActiveProfileName()
}

// Non-interactive mode if both key and secret are provided via flags
if apiKey != "" && apiSecret != "" {
return saveConfigure(&config.Config{APIKey: apiKey, APISecret: apiSecret})
return saveConfigure(&config.Config{APIKey: apiKey, APISecret: apiSecret}, profileName)
}

// Interactive mode
reader := bufio.NewReader(os.Stdin)

_, _ = fmt.Fprintln(out(), "solactl 초기 설정")
_, _ = fmt.Fprintln(out(), "API Key는 https://console.solapi.com 에서 발급받을 수 있습니다.")
_, _ = fmt.Fprintf(errOut(), "프로필: %s\n", profileName)
_, _ = fmt.Fprintln(out())

// Load existing config for defaults
existing, _ := config.Load(nil)
existing, _ := config.Load(&config.LoadOptions{ProfileName: profileName})

// API Key
if apiKey == "" {
Expand Down Expand Up @@ -95,20 +104,21 @@ func runConfigure(cmd *cobra.Command, args []string) error {
return fmt.Errorf("API Secret을 입력하세요")
}

return saveConfigure(&config.Config{APIKey: apiKey, APISecret: apiSecret})
return saveConfigure(&config.Config{APIKey: apiKey, APISecret: apiSecret}, profileName)
}

func saveConfigure(cfg *config.Config) error {
func saveConfigure(cfg *config.Config, profileName string) error {
if err := cfg.Validate(); err != nil {
return err
}

if err := config.Save(cfg); err != nil {
if err := config.Save(cfg, profileName); err != nil {
return fmt.Errorf("설정 저장 실패: %w", err)
}

path, _ := config.ConfigFilePath()
_, _ = fmt.Fprintf(out(), "설정이 저장되었습니다: %s\n", path)
_, _ = fmt.Fprintf(out(), " 프로필: %s\n", profileName)
_, _ = fmt.Fprintf(out(), " API Key: %s\n", cfg.APIKey)
_, _ = fmt.Fprintf(out(), " API Secret: %s\n", config.MaskSecret(cfg.APISecret))
return nil
Expand Down
27 changes: 27 additions & 0 deletions cmd/configure_delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"

"github.com/solapi/solactl/pkg/config"
)

func init() {
configureCmd.AddCommand(&cobra.Command{
Use: "delete <profile>",
Short: "저장된 프로필을 삭제합니다",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
profileName := args[0]

if err := config.DeleteProfile(profileName); err != nil {
return err
}

_, _ = fmt.Fprintf(errOut(), "프로필 '%s'이(가) 삭제되었습니다.\n", profileName)
return nil
},
})
}
47 changes: 47 additions & 0 deletions cmd/configure_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package cmd

import (
"fmt"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The os package needs to be imported to check for file existence errors using os.IsNotExist.

Suggested change
"fmt"
"fmt"
"os"

"os"

"github.com/spf13/cobra"

"github.com/solapi/solactl/pkg/config"
)

func init() {
configureCmd.AddCommand(&cobra.Command{
Use: "list",
Short: "저장된 프로필 목록을 표시합니다",
RunE: func(cmd *cobra.Command, args []string) error {
profiles, err := config.ListProfiles()
if err != nil {
if os.IsNotExist(err) {
_, _ = fmt.Fprintf(errOut(), "프로필이 없습니다. 'solactl configure'를 실행하세요.\n")
return nil
}
return fmt.Errorf("프로필 목록 조회 실패: %w", err)
}
Comment on lines +18 to +24
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation swallows all errors from config.ListProfiles() and provides a generic "No profiles" message. If the configuration file is corrupted or unreadable due to permission issues, this message is misleading and the command incorrectly returns a success exit code (0). It is better to specifically check for the 'file not found' case and return other errors to the caller.

if err != nil {
	if os.IsNotExist(err) {
		_, _ = fmt.Fprintf(errOut(), "프로필이 없습니다. 'solactl configure'를 실행하세요.\n")
		return nil
	}
	return err
}


if len(profiles) == 0 {
_, _ = fmt.Fprintf(errOut(), "프로필이 없습니다. 'solactl configure'를 실행하세요.\n")
return nil
}

p := printer()
for _, prof := range profiles {
active := ""
if prof.Active {
active = " *"
}
p.PrintKeyValue(
"Profile", prof.Name+active,
"API Key", prof.Config.APIKey,
"API Secret", config.MaskSecret(prof.Config.APISecret),
)
_, _ = fmt.Fprintln(out())
}
return nil
},
})
}
8 changes: 7 additions & 1 deletion cmd/configure_show.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@ func init() {
Use: "show",
Short: "현재 설정을 표시합니다",
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.Load(nil)
cfg, err := config.Load(&config.LoadOptions{ProfileName: flagProfile})
if err != nil {
return err
}

profileName := flagProfile
if profileName == "" {
profileName, _ = config.ActiveProfileName()
}

path, _ := config.ConfigFilePath()
p := printer()
p.PrintKeyValue(
"Config File", path,
"Profile", profileName,
"API Key", cfg.APIKey,
"API Secret", config.MaskSecret(cfg.APISecret),
)
Expand Down
Loading