Skip to content

Commit 324407f

Browse files
feat: refactor backup command to use GetRequiredString for interactive prompts
- Replace PromptIfMissing calls with GetRequiredString for host, user, repo-dir, password-file, and paths flags - Add help text for each prompt explaining the purpose of each field - Check flag.Changed() status before prompting to respect explicitly set flags - Remove unused CephClient method stub tests from platform_compatibility_test.go
1 parent c87a7b7 commit 324407f

3 files changed

Lines changed: 109 additions & 54 deletions

File tree

cmd/create/backup.go

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,65 @@ var CreateBackupCmd = &cobra.Command{
4343
then creates a backup of specified directories.`,
4444
RunE: eos.Wrap(func(rc *eos_io.RuntimeContext, cmd *cobra.Command, args []string) error {
4545

46-
backupOpts.Host, _ = interaction.PromptIfMissing(rc.Ctx, cmd, "host", "Enter backup host", false)
47-
backupOpts.User, _ = interaction.PromptIfMissing(rc.Ctx, cmd, "user", "Enter backup user", false)
48-
backupOpts.RepoDir, _ = interaction.PromptIfMissing(rc.Ctx, cmd, "repo-dir", "Enter remote restic repo directory", false)
49-
backupOpts.PasswordFile, _ = interaction.PromptIfMissing(rc.Ctx, cmd, "password-file", "Enter restic password file", false)
50-
pathsFlag, _ = interaction.PromptIfMissing(rc.Ctx, cmd, "paths", "Enter paths to backup (comma separated)", false)
46+
hostFlag, _ := cmd.Flags().GetString("host")
47+
hostWasSet := cmd.Flags().Changed("host")
48+
hostResult, err := interaction.GetRequiredString(rc, hostFlag, hostWasSet, &interaction.RequiredFlagConfig{
49+
FlagName: "host",
50+
PromptMessage: "Enter backup host: ",
51+
HelpText: "Hostname or IP of the restic repository server",
52+
})
53+
if err != nil {
54+
return err
55+
}
56+
backupOpts.Host = hostResult.Value
57+
58+
userFlag, _ := cmd.Flags().GetString("user")
59+
userWasSet := cmd.Flags().Changed("user")
60+
userResult, err := interaction.GetRequiredString(rc, userFlag, userWasSet, &interaction.RequiredFlagConfig{
61+
FlagName: "user",
62+
PromptMessage: "Enter backup user: ",
63+
HelpText: "SSH user used to connect to the backup server",
64+
})
65+
if err != nil {
66+
return err
67+
}
68+
backupOpts.User = userResult.Value
69+
70+
repoFlag, _ := cmd.Flags().GetString("repo-dir")
71+
repoWasSet := cmd.Flags().Changed("repo-dir")
72+
repoResult, err := interaction.GetRequiredString(rc, repoFlag, repoWasSet, &interaction.RequiredFlagConfig{
73+
FlagName: "repo-dir",
74+
PromptMessage: "Enter remote restic repo directory: ",
75+
HelpText: "Directory on the backup host that stores restic repositories",
76+
})
77+
if err != nil {
78+
return err
79+
}
80+
backupOpts.RepoDir = repoResult.Value
81+
82+
passwordFileFlag, _ := cmd.Flags().GetString("password-file")
83+
passwordFileWasSet := cmd.Flags().Changed("password-file")
84+
passwordFileResult, err := interaction.GetRequiredString(rc, passwordFileFlag, passwordFileWasSet, &interaction.RequiredFlagConfig{
85+
FlagName: "password-file",
86+
PromptMessage: "Enter restic password file: ",
87+
HelpText: "Local file path that stores the restic repository password",
88+
})
89+
if err != nil {
90+
return err
91+
}
92+
backupOpts.PasswordFile = passwordFileResult.Value
93+
94+
pathsFlagValue, _ := cmd.Flags().GetString("paths")
95+
pathsWasSet := cmd.Flags().Changed("paths")
96+
pathsResult, err := interaction.GetRequiredString(rc, pathsFlagValue, pathsWasSet, &interaction.RequiredFlagConfig{
97+
FlagName: "paths",
98+
PromptMessage: "Enter paths to backup (comma separated): ",
99+
HelpText: "Specify one or more directories to include in the restic backup",
100+
})
101+
if err != nil {
102+
return err
103+
}
104+
pathsFlag = pathsResult.Value
51105
if pathsFlag != "" {
52106
for _, p := range strings.Split(pathsFlag, ",") {
53107
p = strings.TrimSpace(p)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//go:build darwin
2+
// +build darwin
3+
4+
package cephfs
5+
6+
import (
7+
"testing"
8+
9+
"github.com/CodeMonkeyCybersecurity/eos/pkg/testutil"
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
// TestCephClientStubMethods exercises stubbed CephClient methods that only
14+
// exist on macOS builds to ensure they return platform errors.
15+
func TestCephClientStubMethods(t *testing.T) {
16+
rc := testutil.TestContext(t)
17+
18+
config := &ClientConfig{
19+
ClusterName: "ceph",
20+
User: "admin",
21+
MonHosts: []string{"10.0.0.1"},
22+
}
23+
24+
client, _ := NewCephClient(rc, config)
25+
stubClient := &CephClient{}
26+
27+
err := stubClient.Connect()
28+
assert.Error(t, err)
29+
assert.Contains(t, err.Error(), "not available")
30+
31+
stats, err := stubClient.GetClusterStats()
32+
assert.Error(t, err)
33+
assert.Nil(t, stats)
34+
35+
exists, err := stubClient.VolumeExists(rc, "test")
36+
assert.Error(t, err)
37+
assert.False(t, exists)
38+
39+
volumes, err := stubClient.ListVolumes(rc)
40+
assert.Error(t, err)
41+
assert.Nil(t, volumes)
42+
43+
err = stubClient.CreateVolume(rc, &VolumeCreateOptions{Name: "test"})
44+
assert.Error(t, err)
45+
46+
err = stubClient.DeleteVolume(rc, "test", false)
47+
assert.Error(t, err)
48+
49+
assert.Nil(t, client, "NewCephClient should return nil client on macOS")
50+
}

pkg/cephfs/platform_compatibility_test.go

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -115,55 +115,6 @@ func TestPlatformStubBehavior(t *testing.T) {
115115
}
116116
})
117117

118-
// Test CephClient method stubs
119-
t.Run("CephClient_methods_return_platform_errors", func(t *testing.T) {
120-
if runtime.GOOS != "darwin" {
121-
t.Skip("This test only runs on macOS to verify stubs")
122-
}
123-
124-
config := &ClientConfig{
125-
ClusterName: "ceph",
126-
User: "admin",
127-
MonHosts: []string{"10.0.0.1"},
128-
}
129-
130-
client, _ := NewCephClient(rc, config)
131-
// client will be nil on macOS, but we can test the methods on a zero-value struct
132-
stubClient := &CephClient{}
133-
134-
// Test Connect stub
135-
err := stubClient.Connect()
136-
assert.Error(t, err)
137-
assert.Contains(t, err.Error(), "not available")
138-
139-
// Test GetClusterStats stub
140-
stats, err := stubClient.GetClusterStats()
141-
assert.Error(t, err)
142-
assert.Nil(t, stats)
143-
144-
// Test VolumeExists stub
145-
exists, err := stubClient.VolumeExists(rc, "test")
146-
assert.Error(t, err)
147-
assert.False(t, exists)
148-
149-
// Test ListVolumes stub
150-
volumes, err := stubClient.ListVolumes(rc)
151-
assert.Error(t, err)
152-
assert.Nil(t, volumes)
153-
154-
// Test CreateVolume stub (method, not function)
155-
err = stubClient.CreateVolume(rc, &VolumeCreateOptions{
156-
Name: "test",
157-
})
158-
assert.Error(t, err)
159-
160-
// Test DeleteVolume stub
161-
err = stubClient.DeleteVolume(rc, "test", false)
162-
assert.Error(t, err)
163-
164-
// Client should be nil on macOS
165-
assert.Nil(t, client, "NewCephClient should return nil client on macOS")
166-
})
167118
}
168119

169120
// TestValidateConfig_CrossPlatform verifies validation works on all platforms

0 commit comments

Comments
 (0)