Skip to content

Commit 5f92872

Browse files
authored
feat(sfs): Onboard snaptshot update command (#1403)
STACKITCLI-393 Signed-off-by: Alexander Dahmen <alexander.dahmen@inovex.de>
1 parent 1640792 commit 5f92872

5 files changed

Lines changed: 448 additions & 0 deletions

File tree

docs/stackit_beta_sfs_snapshot.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,5 @@ stackit beta sfs snapshot [flags]
3434
* [stackit beta sfs snapshot delete](./stackit_beta_sfs_snapshot_delete.md) - Deletes a snapshot
3535
* [stackit beta sfs snapshot describe](./stackit_beta_sfs_snapshot_describe.md) - Shows details of a snapshot
3636
* [stackit beta sfs snapshot list](./stackit_beta_sfs_snapshot_list.md) - Lists all snapshots of a resource pool
37+
* [stackit beta sfs snapshot update](./stackit_beta_sfs_snapshot_update.md) - Updates a new snapshot of a resource pool
3738

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
## stackit beta sfs snapshot update
2+
3+
Updates a new snapshot of a resource pool
4+
5+
### Synopsis
6+
7+
Updates a new snapshot of a resource pool.
8+
9+
```
10+
stackit beta sfs snapshot update SNAPSHOT_NAME [flags]
11+
```
12+
13+
### Examples
14+
15+
```
16+
Updates the name of a snapshot with name "snapshot-name" of a resource pool with ID "xxx"
17+
$ stackit beta sfs snapshot update snapshot-name --resource-pool-id xxx --name new-snapshot-name
18+
19+
Updates the comment of a snapshot with name "snapshot-name" of a resource pool with ID "xxx"
20+
$ stackit beta sfs snapshot update snapshot-name --resource-pool-id xxx --comment "snapshot-comment"
21+
```
22+
23+
### Options
24+
25+
```
26+
--comment string A comment to add more information to the snapshot
27+
-h, --help Help for "stackit beta sfs snapshot update"
28+
--name string Snapshot name
29+
--resource-pool-id string The resource pool from which the snapshot should be updated
30+
```
31+
32+
### Options inherited from parent commands
33+
34+
```
35+
-y, --assume-yes If set, skips all confirmation prompts
36+
--async If set, runs the command asynchronously
37+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
38+
-p, --project-id string Project ID
39+
--region string Target region for region-specific requests
40+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
41+
```
42+
43+
### SEE ALSO
44+
45+
* [stackit beta sfs snapshot](./stackit_beta_sfs_snapshot.md) - Provides functionality for SFS snapshots
46+

internal/cmd/beta/sfs/snapshot/snapshot.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/snapshot/delete"
66
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/snapshot/describe"
77
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/snapshot/list"
8+
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/snapshot/update"
89
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
910
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
1011
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
@@ -29,4 +30,5 @@ func addSubcommands(cmd *cobra.Command, params *types.CmdParams) {
2930
cmd.AddCommand(delete.NewCmd(params))
3031
cmd.AddCommand(describe.NewCmd(params))
3132
cmd.AddCommand(list.NewCmd(params))
33+
cmd.AddCommand(update.NewCmd(params))
3234
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package update
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/spf13/cobra"
8+
sfs "github.com/stackitcloud/stackit-sdk-go/services/sfs/v1api"
9+
10+
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
11+
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
14+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
15+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
16+
"github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client"
17+
sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils"
18+
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
19+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
20+
)
21+
22+
const (
23+
snapshotNameArg = "SNAPSHOT_NAME"
24+
25+
resourcePoolIdFlag = "resource-pool-id"
26+
newSnapshotNameFlag = "name"
27+
commentFlag = "comment"
28+
)
29+
30+
type inputModel struct {
31+
*globalflags.GlobalFlagModel
32+
ResourcePoolId string
33+
SnapshotName string
34+
NewSnapshotName string
35+
Comment *string
36+
}
37+
38+
func NewCmd(params *types.CmdParams) *cobra.Command {
39+
cmd := &cobra.Command{
40+
Use: fmt.Sprintf("update %s", snapshotNameArg),
41+
Short: "Updates a new snapshot of a resource pool",
42+
Long: "Updates a new snapshot of a resource pool.",
43+
Args: args.SingleArg(snapshotNameArg, nil),
44+
Example: examples.Build(
45+
examples.NewExample(
46+
`Updates the name of a snapshot with name "snapshot-name" of a resource pool with ID "xxx"`,
47+
"$ stackit beta sfs snapshot update snapshot-name --resource-pool-id xxx --name new-snapshot-name",
48+
),
49+
examples.NewExample(
50+
`Updates the comment of a snapshot with name "snapshot-name" of a resource pool with ID "xxx"`,
51+
`$ stackit beta sfs snapshot update snapshot-name --resource-pool-id xxx --comment "snapshot-comment"`,
52+
),
53+
),
54+
RunE: func(cmd *cobra.Command, args []string) error {
55+
ctx := context.Background()
56+
model, err := parseInput(params.Printer, cmd, args)
57+
if err != nil {
58+
return err
59+
}
60+
61+
// Configure API client
62+
apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion)
63+
if err != nil {
64+
return err
65+
}
66+
67+
resourcePoolLabel, err := sfsUtils.GetResourcePoolName(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ResourcePoolId)
68+
if err != nil {
69+
params.Printer.Debug(print.ErrorLevel, "get resource pool name: %v", err)
70+
resourcePoolLabel = model.ResourcePoolId
71+
} else if resourcePoolLabel == "" {
72+
resourcePoolLabel = model.ResourcePoolId
73+
}
74+
75+
prompt := fmt.Sprintf("Are you sure you want to update the snapshot %q for resource pool %q?", model.SnapshotName, resourcePoolLabel)
76+
err = params.Printer.PromptForConfirmation(prompt)
77+
if err != nil {
78+
return err
79+
}
80+
81+
// Call API
82+
req := buildRequest(ctx, model, apiClient)
83+
resp, err := req.Execute()
84+
if err != nil {
85+
return fmt.Errorf("update snapshot: %w", err)
86+
}
87+
88+
return outputResult(params.Printer, model.OutputFormat, model.SnapshotName, resourcePoolLabel, resp)
89+
},
90+
}
91+
configureFlags(cmd)
92+
return cmd
93+
}
94+
95+
func configureFlags(cmd *cobra.Command) {
96+
cmd.Flags().String(newSnapshotNameFlag, "", "Snapshot name")
97+
cmd.Flags().String(commentFlag, "", "A comment to add more information to the snapshot")
98+
cmd.Flags().Var(flags.UUIDFlag(), resourcePoolIdFlag, "The resource pool from which the snapshot should be updated")
99+
100+
cmd.MarkFlagsOneRequired(newSnapshotNameFlag, commentFlag)
101+
err := flags.MarkFlagsRequired(cmd, resourcePoolIdFlag)
102+
cobra.CheckErr(err)
103+
}
104+
105+
func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiUpdateResourcePoolSnapshotRequest {
106+
req := apiClient.DefaultAPI.UpdateResourcePoolSnapshot(ctx, model.ProjectId, model.Region, model.ResourcePoolId, model.SnapshotName)
107+
108+
payload := sfs.UpdateResourcePoolSnapshotPayload{
109+
Comment: *sfs.NewNullableString(model.Comment),
110+
}
111+
112+
if model.NewSnapshotName != "" {
113+
payload.Name = *sfs.NewNullableString(utils.Ptr(model.NewSnapshotName))
114+
}
115+
return req.UpdateResourcePoolSnapshotPayload(payload)
116+
}
117+
118+
func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) {
119+
snapshotName := inputArgs[0]
120+
globalFlags := globalflags.Parse(p, cmd)
121+
if globalFlags.ProjectId == "" {
122+
return nil, &errors.ProjectIdError{}
123+
}
124+
125+
model := inputModel{
126+
GlobalFlagModel: globalFlags,
127+
SnapshotName: snapshotName,
128+
NewSnapshotName: flags.FlagToStringValue(p, cmd, newSnapshotNameFlag),
129+
ResourcePoolId: flags.FlagToStringValue(p, cmd, resourcePoolIdFlag),
130+
Comment: flags.FlagToStringPointer(p, cmd, commentFlag),
131+
}
132+
133+
p.DebugInputModel(model)
134+
return &model, nil
135+
}
136+
137+
func outputResult(p *print.Printer, outputFormat, snapshotLabel, resourcePoolLabel string, resp *sfs.UpdateResourcePoolSnapshotResponse) error {
138+
return p.OutputResult(outputFormat, resp, func() error {
139+
if resp == nil || resp.ResourcePoolSnapshot == nil {
140+
p.Outputln("SFS snapshot response is empty")
141+
return nil
142+
}
143+
144+
p.Outputf(
145+
"Updated snapshot %q for resource pool %q.\n",
146+
snapshotLabel,
147+
resourcePoolLabel,
148+
)
149+
return nil
150+
})
151+
}

0 commit comments

Comments
 (0)