🚀 Big News:Socket Has Acquired Secure Annex.Learn More
Socket
Book a DemoSign in
Socket

mygithub.libinneed.workers.dev/stackitcloud/stackit-cli

Package Overview
Dependencies
Versions
178
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mygithub.libinneed.workers.dev/stackitcloud/stackit-cli - go Package Compare versions

Comparing version
v0.57.0
to
v0.58.0
+40
docs/stackit_object-storage_compliance-lock_describe.md
## stackit object-storage compliance-lock describe
Describe object storage compliance lock
### Synopsis
Describe object storage compliance lock.
```
stackit object-storage compliance-lock describe [flags]
```
### Examples
```
Describe object storage compliance lock
$ stackit object-storage compliance-lock describe
```
### Options
```
-h, --help Help for "stackit object-storage compliance-lock describe"
```
### Options inherited from parent commands
```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
-p, --project-id string Project ID
--region string Target region for region-specific requests
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
```
### SEE ALSO
* [stackit object-storage compliance-lock](./stackit_object-storage_compliance-lock.md) - Provides functionality to manage Object Storage compliance lock
## stackit object-storage compliance-lock lock
Create object storage compliance lock
### Synopsis
Create object storage compliance lock.
```
stackit object-storage compliance-lock lock [flags]
```
### Examples
```
Create object storage compliance lock
$ stackit object-storage compliance-lock lock
```
### Options
```
-h, --help Help for "stackit object-storage compliance-lock lock"
```
### Options inherited from parent commands
```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
-p, --project-id string Project ID
--region string Target region for region-specific requests
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
```
### SEE ALSO
* [stackit object-storage compliance-lock](./stackit_object-storage_compliance-lock.md) - Provides functionality to manage Object Storage compliance lock
## stackit object-storage compliance-lock unlock
Delete object storage compliance lock
### Synopsis
Delete object storage compliance lock.
```
stackit object-storage compliance-lock unlock [flags]
```
### Examples
```
Delete object storage compliance lock
$ stackit object-storage compliance-lock unlock
```
### Options
```
-h, --help Help for "stackit object-storage compliance-lock unlock"
```
### Options inherited from parent commands
```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
-p, --project-id string Project ID
--region string Target region for region-specific requests
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
```
### SEE ALSO
* [stackit object-storage compliance-lock](./stackit_object-storage_compliance-lock.md) - Provides functionality to manage Object Storage compliance lock
## stackit object-storage compliance-lock
Provides functionality to manage Object Storage compliance lock
### Synopsis
Provides functionality to manage Object Storage compliance lock.
```
stackit object-storage compliance-lock [flags]
```
### Options
```
-h, --help Help for "stackit object-storage compliance-lock"
```
### Options inherited from parent commands
```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
-p, --project-id string Project ID
--region string Target region for region-specific requests
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
```
### SEE ALSO
* [stackit object-storage](./stackit_object-storage.md) - Provides functionality for Object Storage
* [stackit object-storage compliance-lock describe](./stackit_object-storage_compliance-lock_describe.md) - Describe object storage compliance lock
* [stackit object-storage compliance-lock lock](./stackit_object-storage_compliance-lock_lock.md) - Create object storage compliance lock
* [stackit object-storage compliance-lock unlock](./stackit_object-storage_compliance-lock_unlock.md) - Delete object storage compliance lock
package compliancelock
import (
"github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/compliance-lock/describe"
"github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/compliance-lock/lock"
"github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/compliance-lock/unlock"
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
"github.com/spf13/cobra"
)
func NewCmd(params *types.CmdParams) *cobra.Command {
cmd := &cobra.Command{
Use: "compliance-lock",
Short: "Provides functionality to manage Object Storage compliance lock",
Long: "Provides functionality to manage Object Storage compliance lock.",
Args: args.NoArgs,
Run: utils.CmdHelp,
}
addSubcommands(cmd, params)
return cmd
}
func addSubcommands(cmd *cobra.Command, params *types.CmdParams) {
cmd.AddCommand(lock.NewCmd(params))
cmd.AddCommand(unlock.NewCmd(params))
cmd.AddCommand(describe.NewCmd(params))
}
package describe
import (
"context"
"testing"
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
"github.com/stackitcloud/stackit-cli/internal/pkg/testutils"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/google/uuid"
objectstorage "github.com/stackitcloud/stackit-sdk-go/services/objectstorage/v2api"
)
type testCtxKey struct{}
var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo")
var testClient = &objectstorage.APIClient{DefaultAPI: &objectstorage.DefaultAPIService{}}
var testProjectId = uuid.NewString()
const (
testRegion = "eu01"
)
func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string {
flagValues := map[string]string{
globalflags.ProjectIdFlag: testProjectId,
globalflags.RegionFlag: testRegion,
}
for _, mod := range mods {
mod(flagValues)
}
return flagValues
}
func fixtureInputModel(mods ...func(model *inputModel)) *inputModel {
model := &inputModel{
GlobalFlagModel: &globalflags.GlobalFlagModel{
ProjectId: testProjectId,
Region: testRegion,
Verbosity: globalflags.VerbosityDefault,
},
}
for _, mod := range mods {
mod(model)
}
return model
}
func fixtureRequest(mods ...func(request *objectstorage.ApiGetComplianceLockRequest)) objectstorage.ApiGetComplianceLockRequest {
request := testClient.DefaultAPI.GetComplianceLock(testCtx, testProjectId, testRegion)
for _, mod := range mods {
mod(&request)
}
return request
}
func TestParseInput(t *testing.T) {
tests := []struct {
description string
flagValues map[string]string
isValid bool
expectedModel *inputModel
}{
{
description: "base",
flagValues: fixtureFlagValues(),
isValid: true,
expectedModel: fixtureInputModel(),
},
{
description: "project id missing",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
delete(flagValues, globalflags.ProjectIdFlag)
}),
isValid: false,
},
{
description: "project id invalid 1",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[globalflags.ProjectIdFlag] = ""
}),
isValid: false,
},
{
description: "project id invalid 2",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[globalflags.ProjectIdFlag] = "invalid-uuid"
}),
isValid: false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, nil, tt.flagValues, tt.isValid)
})
}
}
func TestBuildRequest(t *testing.T) {
tests := []struct {
description string
model *inputModel
expectedRequest objectstorage.ApiGetComplianceLockRequest
}{
{
description: "base",
model: fixtureInputModel(),
expectedRequest: fixtureRequest(),
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
request := buildRequest(testCtx, tt.model, testClient)
diff := cmp.Diff(request, tt.expectedRequest,
cmp.AllowUnexported(tt.expectedRequest, objectstorage.DefaultAPIService{}),
cmpopts.EquateComparable(testCtx),
)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
})
}
}
func TestOutputResult(t *testing.T) {
type args struct {
outputFormat string
complianceLock *objectstorage.ComplianceLockResponse
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "empty",
args: args{
outputFormat: print.PrettyOutputFormat,
},
wantErr: true,
},
{
name: "set empty compliance lock",
args: args{
outputFormat: print.PrettyOutputFormat,
complianceLock: &objectstorage.ComplianceLockResponse{},
},
wantErr: false,
},
{
name: "set filled lock",
args: args{
outputFormat: print.PrettyOutputFormat,
complianceLock: &objectstorage.ComplianceLockResponse{
Project: uuid.New().String(),
MaxRetentionDays: int32(42),
},
},
wantErr: false,
},
}
p := print.NewPrinter()
p.Cmd = NewCmd(&types.CmdParams{Printer: p})
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := outputResult(p, tt.args.outputFormat, tt.args.complianceLock); (err != nil) != tt.wantErr {
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
package describe
import (
"context"
"fmt"
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
"github.com/stackitcloud/stackit-cli/internal/pkg/services/object-storage/client"
objectStorageUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/object-storage/utils"
"github.com/stackitcloud/stackit-cli/internal/pkg/tables"
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/spf13/cobra"
objectstorage "github.com/stackitcloud/stackit-sdk-go/services/objectstorage/v2api"
)
type inputModel struct {
*globalflags.GlobalFlagModel
}
func NewCmd(params *types.CmdParams) *cobra.Command {
cmd := &cobra.Command{
Use: "describe",
Short: "Describe object storage compliance lock",
Long: "Describe object storage compliance lock.",
Args: args.NoArgs,
Example: examples.Build(
examples.NewExample(
`Describe object storage compliance lock`,
"$ stackit object-storage compliance-lock describe"),
),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
model, err := parseInput(params.Printer, cmd, args)
if err != nil {
return err
}
// Configure API client
apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion)
if err != nil {
return err
}
// Check if the project is enabled before trying to describe
enabled, err := objectStorageUtils.ProjectEnabled(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region)
if err != nil {
return fmt.Errorf("check if Object Storage is enabled: %w", err)
}
if !enabled {
return &errors.ServiceDisabledError{
Service: "object-storage",
}
}
// Call API
req := buildRequest(ctx, model, apiClient)
resp, err := req.Execute()
if err != nil {
return fmt.Errorf("get object storage compliance lock: %w", err)
}
return outputResult(params.Printer, model.OutputFormat, resp)
},
}
return cmd
}
func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) {
globalFlags := globalflags.Parse(p, cmd)
if globalFlags.ProjectId == "" {
return nil, &errors.ProjectIdError{}
}
model := inputModel{
GlobalFlagModel: globalFlags,
}
p.DebugInputModel(model)
return &model, nil
}
func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiGetComplianceLockRequest {
req := apiClient.DefaultAPI.GetComplianceLock(ctx, model.ProjectId, model.Region)
return req
}
func outputResult(p *print.Printer, outputFormat string, resp *objectstorage.ComplianceLockResponse) error {
return p.OutputResult(outputFormat, resp, func() error {
if resp == nil {
return fmt.Errorf("response is empty")
}
table := tables.NewTable()
table.AddRow("PROJECT ID", resp.Project)
table.AddSeparator()
table.AddRow("MAX RETENTION DAYS", resp.MaxRetentionDays)
table.AddSeparator()
err := table.Display(p)
if err != nil {
return fmt.Errorf("render table: %w", err)
}
return nil
})
}
package lock
import (
"context"
"testing"
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
"github.com/stackitcloud/stackit-cli/internal/pkg/testutils"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/google/uuid"
objectstorage "github.com/stackitcloud/stackit-sdk-go/services/objectstorage/v2api"
)
type testCtxKey struct{}
var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo")
var testClient = &objectstorage.APIClient{DefaultAPI: &objectstorage.DefaultAPIService{}}
var testProjectId = uuid.NewString()
const (
testRegion = "eu01"
)
func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string {
flagValues := map[string]string{
globalflags.ProjectIdFlag: testProjectId,
globalflags.RegionFlag: testRegion,
}
for _, mod := range mods {
mod(flagValues)
}
return flagValues
}
func fixtureInputModel(mods ...func(model *inputModel)) *inputModel {
model := &inputModel{
GlobalFlagModel: &globalflags.GlobalFlagModel{
ProjectId: testProjectId,
Region: testRegion,
Verbosity: globalflags.VerbosityDefault,
},
}
for _, mod := range mods {
mod(model)
}
return model
}
func fixtureRequest(mods ...func(request *objectstorage.ApiCreateComplianceLockRequest)) objectstorage.ApiCreateComplianceLockRequest {
request := testClient.DefaultAPI.CreateComplianceLock(testCtx, testProjectId, testRegion)
for _, mod := range mods {
mod(&request)
}
return request
}
func TestParseInput(t *testing.T) {
tests := []struct {
description string
flagValues map[string]string
isValid bool
expectedModel *inputModel
}{
{
description: "base",
flagValues: fixtureFlagValues(),
isValid: true,
expectedModel: fixtureInputModel(),
},
{
description: "project id missing",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
delete(flagValues, globalflags.ProjectIdFlag)
}),
isValid: false,
},
{
description: "project id invalid 1",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[globalflags.ProjectIdFlag] = ""
}),
isValid: false,
},
{
description: "project id invalid 2",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[globalflags.ProjectIdFlag] = "invalid-uuid"
}),
isValid: false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, nil, tt.flagValues, tt.isValid)
})
}
}
func TestBuildRequest(t *testing.T) {
tests := []struct {
description string
model *inputModel
expectedRequest objectstorage.ApiCreateComplianceLockRequest
}{
{
description: "base",
model: fixtureInputModel(),
expectedRequest: fixtureRequest(),
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
request := buildRequest(testCtx, tt.model, testClient)
diff := cmp.Diff(request, tt.expectedRequest,
cmp.AllowUnexported(tt.expectedRequest, objectstorage.DefaultAPIService{}),
cmpopts.EquateComparable(testCtx),
)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
})
}
}
func TestOutputResult(t *testing.T) {
type args struct {
outputFormat string
projectLabel string
complianceLock *objectstorage.ComplianceLockResponse
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "empty",
args: args{
outputFormat: print.PrettyOutputFormat,
},
wantErr: true,
},
{
name: "set empty compliance lock",
args: args{
outputFormat: print.PrettyOutputFormat,
complianceLock: &objectstorage.ComplianceLockResponse{},
},
wantErr: false,
},
{
name: "set filled lock",
args: args{
outputFormat: print.PrettyOutputFormat,
complianceLock: &objectstorage.ComplianceLockResponse{
Project: uuid.New().String(),
MaxRetentionDays: int32(42),
},
},
wantErr: false,
},
}
p := print.NewPrinter()
p.Cmd = NewCmd(&types.CmdParams{Printer: p})
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.complianceLock); (err != nil) != tt.wantErr {
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
package lock
import (
"context"
"fmt"
"github.com/stackitcloud/stackit-cli/internal/pkg/projectname"
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
"github.com/stackitcloud/stackit-cli/internal/pkg/services/object-storage/client"
"github.com/stackitcloud/stackit-cli/internal/pkg/services/object-storage/utils"
"github.com/spf13/cobra"
objectstorage "github.com/stackitcloud/stackit-sdk-go/services/objectstorage/v2api"
)
type inputModel struct {
*globalflags.GlobalFlagModel
}
func NewCmd(params *types.CmdParams) *cobra.Command {
cmd := &cobra.Command{
Use: "lock",
Short: "Create object storage compliance lock",
Long: "Create object storage compliance lock.",
Args: args.NoArgs,
Example: examples.Build(
examples.NewExample(
`Create object storage compliance lock`,
"$ stackit object-storage compliance-lock lock"),
),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
model, err := parseInput(params.Printer, cmd, args)
if err != nil {
return err
}
// Configure API client
apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion)
if err != nil {
return err
}
projectLabel, err := projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd)
if err != nil {
params.Printer.Debug(print.ErrorLevel, "get project name: %v", err)
projectLabel = model.ProjectId
} else if projectLabel == "" {
projectLabel = model.ProjectId
}
prompt := fmt.Sprintf("Are you sure you want to create object storage compliance-lock for project %s?", projectLabel)
err = params.Printer.PromptForConfirmation(prompt)
if err != nil {
return err
}
// Check if the project is enabled before trying to create
enabled, err := utils.ProjectEnabled(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region)
if err != nil {
return fmt.Errorf("check if Object Storage is enabled: %w", err)
}
if !enabled {
return &errors.ServiceDisabledError{
Service: "object-storage",
}
}
// Call API
req := buildRequest(ctx, model, apiClient)
resp, err := req.Execute()
if err != nil {
return fmt.Errorf("create object storage compliance lock: %w", err)
}
return outputResult(params.Printer, model.OutputFormat, projectLabel, resp)
},
}
return cmd
}
func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) {
globalFlags := globalflags.Parse(p, cmd)
if globalFlags.ProjectId == "" {
return nil, &errors.ProjectIdError{}
}
model := inputModel{
GlobalFlagModel: globalFlags,
}
p.DebugInputModel(model)
return &model, nil
}
func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiCreateComplianceLockRequest {
req := apiClient.DefaultAPI.CreateComplianceLock(ctx, model.ProjectId, model.Region)
return req
}
func outputResult(p *print.Printer, outputFormat, projectLabel string, resp *objectstorage.ComplianceLockResponse) error {
return p.OutputResult(outputFormat, resp, func() error {
if resp == nil {
return fmt.Errorf("create compliance lock response is empty")
}
p.Outputf("Created object storage compliance lock for project \"%s\" with maximum retention period of %d days.\n", projectLabel, resp.MaxRetentionDays)
return nil
})
}
package unlock
import (
"context"
"testing"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/testutils"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/google/uuid"
objectstorage "github.com/stackitcloud/stackit-sdk-go/services/objectstorage/v2api"
)
type testCtxKey struct{}
var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo")
var testClient = &objectstorage.APIClient{DefaultAPI: &objectstorage.DefaultAPIService{}}
var testProjectId = uuid.NewString()
const (
testRegion = "eu01"
)
func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string {
flagValues := map[string]string{
globalflags.ProjectIdFlag: testProjectId,
globalflags.RegionFlag: testRegion,
}
for _, mod := range mods {
mod(flagValues)
}
return flagValues
}
func fixtureInputModel(mods ...func(model *inputModel)) *inputModel {
model := &inputModel{
GlobalFlagModel: &globalflags.GlobalFlagModel{
ProjectId: testProjectId,
Region: testRegion,
Verbosity: globalflags.VerbosityDefault,
},
}
for _, mod := range mods {
mod(model)
}
return model
}
func fixtureRequest(mods ...func(request *objectstorage.ApiDeleteComplianceLockRequest)) objectstorage.ApiDeleteComplianceLockRequest {
request := testClient.DefaultAPI.DeleteComplianceLock(testCtx, testProjectId, testRegion)
for _, mod := range mods {
mod(&request)
}
return request
}
func TestParseInput(t *testing.T) {
tests := []struct {
description string
flagValues map[string]string
isValid bool
expectedModel *inputModel
}{
{
description: "base",
flagValues: fixtureFlagValues(),
isValid: true,
expectedModel: fixtureInputModel(),
},
{
description: "project id missing",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
delete(flagValues, globalflags.ProjectIdFlag)
}),
isValid: false,
},
{
description: "project id invalid 1",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[globalflags.ProjectIdFlag] = ""
}),
isValid: false,
},
{
description: "project id invalid 2",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[globalflags.ProjectIdFlag] = "invalid-uuid"
}),
isValid: false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, nil, tt.flagValues, tt.isValid)
})
}
}
func TestBuildRequest(t *testing.T) {
tests := []struct {
description string
model *inputModel
expectedRequest objectstorage.ApiDeleteComplianceLockRequest
}{
{
description: "base",
model: fixtureInputModel(),
expectedRequest: fixtureRequest(),
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
request := buildRequest(testCtx, tt.model, testClient)
diff := cmp.Diff(request, tt.expectedRequest,
cmp.AllowUnexported(tt.expectedRequest, objectstorage.DefaultAPIService{}),
cmpopts.EquateComparable(testCtx),
)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
})
}
}
package unlock
import (
"context"
"fmt"
"github.com/stackitcloud/stackit-cli/internal/pkg/projectname"
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
"github.com/stackitcloud/stackit-cli/internal/pkg/services/object-storage/client"
"github.com/stackitcloud/stackit-cli/internal/pkg/services/object-storage/utils"
"github.com/spf13/cobra"
objectstorage "github.com/stackitcloud/stackit-sdk-go/services/objectstorage/v2api"
)
type inputModel struct {
*globalflags.GlobalFlagModel
}
func NewCmd(params *types.CmdParams) *cobra.Command {
cmd := &cobra.Command{
Use: "unlock",
Short: "Delete object storage compliance lock",
Long: "Delete object storage compliance lock.",
Args: args.NoArgs,
Example: examples.Build(
examples.NewExample(
`Delete object storage compliance lock`,
"$ stackit object-storage compliance-lock unlock"),
),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
model, err := parseInput(params.Printer, cmd, args)
if err != nil {
return err
}
// Configure API client
apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion)
if err != nil {
return err
}
projectLabel, err := projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd)
if err != nil {
params.Printer.Debug(print.ErrorLevel, "get project name: %v", err)
projectLabel = model.ProjectId
} else if projectLabel == "" {
projectLabel = model.ProjectId
}
prompt := fmt.Sprintf("Are you sure you want to delete object storage compliance-lock for project %s?", projectLabel)
err = params.Printer.PromptForConfirmation(prompt)
if err != nil {
return err
}
// Check if the project is enabled before trying to create
enabled, err := utils.ProjectEnabled(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region)
if err != nil {
return fmt.Errorf("check if Object Storage is enabled: %w", err)
}
if !enabled {
return &errors.ServiceDisabledError{
Service: "object-storage",
}
}
// Call API
_, err = buildRequest(ctx, model, apiClient).Execute()
if err != nil {
return fmt.Errorf("delete object storage compliance lock: %w", err)
}
params.Printer.Outputf("Deleted object storage compliance lock for project \"%s\".\n", projectLabel)
return nil
},
}
return cmd
}
func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) {
globalFlags := globalflags.Parse(p, cmd)
if globalFlags.ProjectId == "" {
return nil, &errors.ProjectIdError{}
}
model := inputModel{
GlobalFlagModel: globalFlags,
}
p.DebugInputModel(model)
return &model, nil
}
func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiDeleteComplianceLockRequest {
req := apiClient.DefaultAPI.DeleteComplianceLock(ctx, model.ProjectId, model.Region)
return req
}
+1
-0

@@ -34,2 +34,3 @@ ## stackit object-storage

* [stackit object-storage bucket](./stackit_object-storage_bucket.md) - Provides functionality for Object Storage buckets
* [stackit object-storage compliance-lock](./stackit_object-storage_compliance-lock.md) - Provides functionality to manage Object Storage compliance lock
* [stackit object-storage credentials](./stackit_object-storage_credentials.md) - Provides functionality for Object Storage credentials

@@ -36,0 +37,0 @@ * [stackit object-storage credentials-group](./stackit_object-storage_credentials-group.md) - Provides functionality for Object Storage credentials group

+10
-3

@@ -21,2 +21,5 @@ ## stackit secrets-manager instance create

$ stackit secrets-manager instance create --name my-instance --acl 1.2.3.0/24
Create a Secrets Manager instance with name "my-instance" and configure KMS key options
$ stackit secrets-manager instance create --name my-instance --kms-key-id key-id --kms-keyring-id keyring-id --kms-key-version 1 --kms-service-account-email my-service-account-1234567@sa.stackit.cloud
```

@@ -27,5 +30,9 @@

```
--acl strings List of IP networks in CIDR notation which are allowed to access this instance (default [])
-h, --help Help for "stackit secrets-manager instance create"
-n, --name string Instance name
--acl strings List of IP networks in CIDR notation which are allowed to access this instance (default [])
-h, --help Help for "stackit secrets-manager instance create"
--kms-key-id string ID of the KMS key to use for encryption
--kms-key-version int Version of the KMS key
--kms-keyring-id string ID of the KMS key ring
--kms-service-account-email string Service account email for KMS access
-n, --name string Instance name
```

@@ -32,0 +39,0 @@

@@ -16,4 +16,13 @@ ## stackit secrets-manager instance update

```
Update the name of a Secrets Manager instance with ID "xxx"
$ stackit secrets-manager instance update xxx --name my-new-name
Update the range of IPs allowed to access a Secrets Manager instance with ID "xxx"
$ stackit secrets-manager instance update xxx --acl 1.2.3.0/24
Update the name and ACLs of a Secrets Manager instance with ID "xxx"
$ stackit secrets-manager instance update xxx --name my-new-name --acl 1.2.3.0/24
Update the KMS key settings of a Secrets Manager instance with ID "xxx"
$ stackit secrets-manager instance update xxx --name my-instance --kms-key-id key-id --kms-keyring-id keyring-id --kms-key-version 1 --kms-service-account-email my-service-account-1234567@sa.stackit.cloud
```

@@ -24,4 +33,9 @@

```
--acl strings List of IP networks in CIDR notation which are allowed to access this instance (default [])
-h, --help Help for "stackit secrets-manager instance update"
--acl strings List of IP networks in CIDR notation which are allowed to access this instance (default [])
-h, --help Help for "stackit secrets-manager instance update"
--kms-key-id string ID of the KMS key to use for encryption
--kms-key-version int Version of the KMS key
--kms-keyring-id string ID of the KMS key ring
--kms-service-account-email string Service account email for KMS access
-n, --name string Instance name
```

@@ -28,0 +42,0 @@

@@ -87,9 +87,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating loadbalancer")
_, err = wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating loadbalancer", func() error {
_, err := wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for loadbalancer creation: %w", err)
}
s.Stop()
}

@@ -96,0 +96,0 @@

@@ -93,10 +93,10 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("updating loadbalancer")
_, err = wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name).
WaitWithContext(ctx)
err := spinner.Run(params.Printer, "updating loadbalancer", func() error {
_, err = wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name).
WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for loadbalancer update: %w", err)
}
s.Stop()
}

@@ -103,0 +103,0 @@

@@ -90,15 +90,14 @@ // SPDX-License-Identifier: Apache-2.0

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
// The waiter handler needs a concrete client type. We can safely cast here as the real implementation will always match.
client, ok := apiClient.(*edge.APIClient)
if !ok {
return fmt.Errorf("failed to configure API client")
}
_, err = wait.CreateOrUpdateInstanceWaitHandler(ctx, client, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
// The waiter handler needs a concrete concreteClient type. We can safely cast here as the real implementation will always match.
concreteClient, ok := apiClient.(*edge.APIClient)
if !ok {
return fmt.Errorf("failed to configure API concreteClient")
}
_, err = wait.CreateOrUpdateInstanceWaitHandler(ctx, concreteClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for edge instance creation: %w", err)
}
s.Stop()
}

@@ -105,0 +104,0 @@

@@ -113,21 +113,22 @@ // SPDX-License-Identifier: Apache-2.0

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
// Determine identifier and waiter to use
waiterFactory, err := getWaiterFactory(ctx, model)
if err != nil {
err := spinner.Run(params.Printer, "Deleting instance", func() error {
// Determine identifier and waiter to use
waiterFactory, err := getWaiterFactory(ctx, model)
if err != nil {
return err
}
// The waiter factory needs a concrete concreteClient type. We can safely cast here as the real implementation will always match.
concreteClient, ok := apiClient.(*edge.APIClient)
if !ok {
return fmt.Errorf("failed to configure API concreteClient")
}
waiter := waiterFactory(concreteClient)
_, err = waiter.WaitWithContext(ctx)
return err
}
// The waiter factory needs a concrete client type. We can safely cast here as the real implementation will always match.
client, ok := apiClient.(*edge.APIClient)
if !ok {
return fmt.Errorf("failed to configure API client")
}
waiter := waiterFactory(client)
})
if _, err = waiter.WaitWithContext(ctx); err != nil {
if err != nil {
return fmt.Errorf("wait for edge instance deletion: %w", err)
}
operationState = "Deleted"
s.Stop()
}

@@ -134,0 +135,0 @@

@@ -123,21 +123,22 @@ // SPDX-License-Identifier: Apache-2.0

// Show spinner while waiting
s := spinner.New(params.Printer)
s.Start("Updating instance")
// Determine identifier and waiter to use
waiterFactory, err := getWaiterFactory(ctx, model)
if err != nil {
err := spinner.Run(params.Printer, "Updating instance", func() error {
// Determine identifier and waiter to use
waiterFactory, err := getWaiterFactory(ctx, model)
if err != nil {
return err
}
// The waiter handler needs a concrete concreteClient type. We can safely cast here as the real implementation will always match.
concreteClient, ok := apiClient.(*edge.APIClient)
if !ok {
return fmt.Errorf("failed to configure API concreteClient")
}
waiter := waiterFactory(concreteClient)
_, err = waiter.WaitWithContext(ctx)
return err
}
// The waiter handler needs a concrete client type. We can safely cast here as the real implementation will always match.
client, ok := apiClient.(*edge.APIClient)
if !ok {
return fmt.Errorf("failed to configure API client")
}
waiter := waiterFactory(client)
})
if _, err = waiter.WaitWithContext(ctx); err != nil {
if err != nil {
return fmt.Errorf("wait for edge instance update: %w", err)
}
operationState = "Updated"
s.Stop()
}

@@ -144,0 +145,0 @@

@@ -114,9 +114,9 @@ package create

if !model.Async {
s := spinner.New(p.Printer)
s.Start("Creating STACKIT Intake instance")
_, err = wait.CreateOrUpdateIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resp.GetId()).WaitWithContext(ctx)
err := spinner.Run(p.Printer, "Creating STACKIT Intake instance", func() error {
_, err = wait.CreateOrUpdateIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resp.GetId()).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for STACKIT Instance creation: %w", err)
}
s.Stop()
}

@@ -123,0 +123,0 @@

@@ -71,9 +71,9 @@ package delete

if !model.Async {
s := spinner.New(p.Printer)
s.Start("Deleting STACKIT Intake instance")
_, err = wait.DeleteIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.IntakeId).WaitWithContext(ctx)
err := spinner.Run(p.Printer, "Deleting STACKIT Intake instance", func() error {
_, err = wait.DeleteIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.IntakeId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for STACKIT Instance deletion: %w", err)
}
s.Stop()
}

@@ -80,0 +80,0 @@

@@ -91,9 +91,9 @@ package create

if !model.Async {
s := spinner.New(p.Printer)
s.Start("Creating STACKIT Intake Runner")
_, err = wait.CreateOrUpdateIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resp.GetId()).WaitWithContext(ctx)
err := spinner.Run(p.Printer, "Creating STACKIT Intake Runner", func() error {
_, err = wait.CreateOrUpdateIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resp.GetId()).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for STACKIT Intake Runner creation: %w", err)
}
s.Stop()
}

@@ -100,0 +100,0 @@

@@ -71,9 +71,9 @@ package delete

if !model.Async {
s := spinner.New(p.Printer)
s.Start("Deleting STACKIT Intake Runner")
_, err = wait.DeleteIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.RunnerId).WaitWithContext(ctx)
err := spinner.Run(p.Printer, "Deleting STACKIT Intake Runner", func() error {
_, err = wait.DeleteIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.RunnerId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for STACKIT Intake Runner deletion: %w", err)
}
s.Stop()
}

@@ -80,0 +80,0 @@

@@ -89,9 +89,9 @@ package update

if !model.Async {
s := spinner.New(p.Printer)
s.Start("Updating STACKIT Intake Runner")
_, err = wait.CreateOrUpdateIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.RunnerId).WaitWithContext(ctx)
err := spinner.Run(p.Printer, "Updating STACKIT Intake Runner", func() error {
_, err = wait.CreateOrUpdateIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.RunnerId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for STACKIT Intake Runner update: %w", err)
}
s.Stop()
}

@@ -98,0 +98,0 @@

@@ -109,9 +109,9 @@ package update

if !model.Async {
s := spinner.New(p.Printer)
s.Start("Updating STACKIT Intake Runner instance")
_, err = wait.CreateOrUpdateIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.IntakeId).WaitWithContext(ctx)
err := spinner.Run(p.Printer, "Updating STACKIT Intake Runner instance", func() error {
_, err = wait.CreateOrUpdateIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.IntakeId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for STACKIT Instance creation: %w", err)
}
s.Stop()
}

@@ -118,0 +118,0 @@

@@ -103,9 +103,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Create resource pool")
_, err = wait.CreateResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resourcePoolId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Create resource pool", func() error {
_, err = wait.CreateResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resourcePoolId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for resource pool creation: %w", err)
}
s.Stop()
}

@@ -112,0 +112,0 @@

@@ -76,9 +76,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Delete resource pool")
_, err = wait.DeleteResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Delete resource pool", func() error {
_, err = wait.DeleteResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for resource pool deletion: %w", err)
}
s.Stop()
}

@@ -85,0 +85,0 @@

@@ -104,9 +104,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Update resource pool")
_, err = wait.UpdateResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Update resource pool", func() error {
_, err = wait.UpdateResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for resource pool update: %w", err)
}
s.Stop()
}

@@ -113,0 +113,0 @@

@@ -94,9 +94,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating share")
_, err = wait.CreateShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, shareId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating share", func() error {
_, err = wait.CreateShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, shareId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("waiting for share creation: %w", err)
}
s.Stop()
}

@@ -103,0 +103,0 @@

@@ -83,9 +83,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting share")
_, err = wait.DeleteShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting share", func() error {
_, err = wait.DeleteShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("waiting for share deletion: %w", err)
}
s.Stop()
}

@@ -92,0 +92,0 @@

@@ -99,9 +99,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating share")
_, err = wait.UpdateShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating share", func() error {
_, err = wait.UpdateShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("waiting for share update: %w", err)
}
s.Stop()
}

@@ -108,0 +108,0 @@

@@ -71,10 +71,8 @@ package create

req := buildRequest(ctx, model, apiClient)
s := spinner.New(params.Printer)
s.Start("Creating database")
resp, err := req.Execute()
resp, err := spinner.Run2(params.Printer, "Creating database", func() (*sqlserverflex.CreateDatabaseResponse, error) {
return req.Execute()
})
if err != nil {
s.StopWithError()
return fmt.Errorf("create SQLServer Flex database: %w", err)
}
s.Stop()

@@ -81,0 +79,0 @@ return outputResult(params.Printer, model.OutputFormat, model.DatabaseName, resp)

@@ -69,10 +69,9 @@ package delete

req := buildRequest(ctx, model, apiClient)
s := spinner.New(params.Printer)
s.Start("Deleting database")
err = req.Execute()
err = spinner.Run(params.Printer, "Deleting database", func() error {
err := req.Execute()
return err
})
if err != nil {
s.StopWithError()
return fmt.Errorf("delete SQLServer Flex database: %w", err)
}
s.Stop()

@@ -79,0 +78,0 @@ params.Printer.Info("Deleted database %q\n", model.DatabaseName)

@@ -125,9 +125,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SQLServer Flex instance creation: %w", err)
}
s.Stop()
}

@@ -134,0 +134,0 @@

@@ -78,9 +78,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting instance", func() error {
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SQLServer Flex instance deletion: %w", err)
}
s.Stop()
}

@@ -87,0 +87,0 @@

@@ -116,9 +116,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating instance")
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating instance", func() error {
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SQLServer Flex instance update: %w", err)
}
s.Stop()
}

@@ -125,0 +125,0 @@

@@ -8,2 +8,3 @@ package create

"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/stackitcloud/stackit-sdk-go/services/dns/wait"

@@ -22,3 +23,2 @@ "github.com/spf13/cobra"

"github.com/stackitcloud/stackit-sdk-go/services/dns"
"github.com/stackitcloud/stackit-sdk-go/services/dns/wait"
)

@@ -94,9 +94,9 @@

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating record set")
_, err = wait.CreateRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, recordSetId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating record set", func() error {
_, err = wait.CreateRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, recordSetId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for DNS record set creation: %w", err)
}
s.Stop()
}

@@ -103,0 +103,0 @@

@@ -91,9 +91,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting record set")
_, err = wait.DeleteRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting record set", func() error {
_, err = wait.DeleteRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for DNS record set deletion: %w", err)
}
s.Stop()
}

@@ -100,0 +100,0 @@

@@ -111,9 +111,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating record set")
_, err = wait.PartialUpdateRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating record set", func() error {
_, err = wait.PartialUpdateRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for DNS record set update: %w", err)
}
s.Stop()
}

@@ -120,0 +120,0 @@

@@ -94,9 +94,9 @@ package clone

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Cloning zone")
_, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Cloning zone", func() error {
_, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for DNS zone cloning: %w", err)
}
s.Stop()
}

@@ -103,0 +103,0 @@

@@ -107,9 +107,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating zone")
_, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating zone", func() error {
_, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for DNS zone creation: %w", err)
}
s.Stop()
}

@@ -116,0 +116,0 @@

@@ -80,9 +80,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting zone")
_, err = wait.DeleteZoneWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting zone", func() error {
_, err = wait.DeleteZoneWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for DNS zone deletion: %w", err)
}
s.Stop()
}

@@ -89,0 +89,0 @@

@@ -103,9 +103,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating zone")
_, err = wait.PartialUpdateZoneWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating zone", func() error {
_, err = wait.PartialUpdateZoneWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for DNS zone update: %w", err)
}
s.Stop()
}

@@ -112,0 +112,0 @@

@@ -84,9 +84,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating stackit git instance")
_, err = wait.CreateGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, *result.Id).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating STACKIT git instance", func() error {
_, err = wait.CreateGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, *result.Id).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for stackit git Instance creation: %w", err)
}
s.Stop()
}

@@ -93,0 +93,0 @@

@@ -84,9 +84,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting stackit git instance")
_, err = wait.DeleteGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting STACKIT git instance", func() error {
_, err = wait.DeleteGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for stackit git instance deletion: %w", err)
}
s.Stop()
}

@@ -93,0 +93,0 @@

@@ -100,9 +100,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating key")
_, err = wait.CreateOrUpdateKeyWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, *resp.Id).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating key", func() error {
_, err = wait.CreateOrUpdateKeyWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, *resp.Id).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for KMS key creation: %w", err)
}
s.Stop()
}

@@ -109,0 +109,0 @@

@@ -87,9 +87,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating key ring")
_, err = wait.CreateKeyRingWaitHandler(ctx, apiClient, model.ProjectId, model.Region, keyRingId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating key ring", func() error {
_, err = wait.CreateKeyRingWaitHandler(ctx, apiClient, model.ProjectId, model.Region, keyRingId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for KMS key ring creation: %w", err)
}
s.Stop()
}

@@ -96,0 +96,0 @@

@@ -73,9 +73,9 @@ package disable

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Disabling key version")
_, err = wait.DisableKeyVersionWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Disabling key version", func() error {
_, err = wait.DisableKeyVersionWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for key version to be disabled: %w", err)
}
s.Stop()
}

@@ -82,0 +82,0 @@

@@ -73,9 +73,9 @@ package enable

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Enabling key version")
_, err = wait.EnableKeyVersionWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Enabling key version", func() error {
_, err = wait.EnableKeyVersionWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for key version to be enabled: %w", err)
}
s.Stop()
}

@@ -82,0 +82,0 @@

@@ -86,9 +86,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating wrapping key")
_, err = wait.CreateWrappingKeyWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *wrappingKey.KeyRingId, *wrappingKey.Id).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating wrapping key", func() error {
_, err = wait.CreateWrappingKeyWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *wrappingKey.KeyRingId, *wrappingKey.Id).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for KMS wrapping key creation: %w", err)
}
s.Stop()
}

@@ -95,0 +95,0 @@

@@ -96,9 +96,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating load balancer")
_, err = wait.CreateLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *model.Payload.Name).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating load balancer", func() error {
_, err = wait.CreateLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *model.Payload.Name).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for load balancer creation: %w", err)
}
s.Stop()
}

@@ -105,0 +105,0 @@

@@ -69,9 +69,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting load balancer")
_, err = wait.DeleteLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.LoadBalancerName).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting load balancer", func() error {
_, err = wait.DeleteLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.LoadBalancerName).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for load balancer deletion: %w", err)
}
s.Stop()
}

@@ -78,0 +78,0 @@

@@ -117,9 +117,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for LogMe instance creation: %w", err)
}
s.Stop()
}

@@ -126,0 +126,0 @@

@@ -78,9 +78,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting instacne", func() error {
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for LogMe instance deletion: %w", err)
}
s.Stop()
}

@@ -87,0 +87,0 @@

@@ -116,9 +116,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating instance")
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating instance", func() error {
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for LogMe instance update: %w", err)
}
s.Stop()
}

@@ -125,0 +125,0 @@

@@ -105,9 +105,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
_, err = wait.CreateLogsInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
_, err = wait.CreateLogsInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for logs instance creation: %w", err)
}
s.Stop()
}

@@ -114,0 +114,0 @@

@@ -88,9 +88,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
_, err = wait.DeleteLogsInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceID).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting instance", func() error {
_, err = wait.DeleteLogsInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceID).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for Logs instance deletion: %w", err)
}
s.Stop()
}

@@ -97,0 +97,0 @@

@@ -117,9 +117,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for MariaDB instance creation: %w", err)
}
s.Stop()
}

@@ -126,0 +126,0 @@

@@ -78,9 +78,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting instance", func() error {
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for MariaDB instance deletion: %w", err)
}
s.Stop()
}

@@ -87,0 +87,0 @@

@@ -114,9 +114,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating instance")
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating instance", func() error {
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for MariaDB instance update: %w", err)
}
s.Stop()
}

@@ -123,0 +123,0 @@

@@ -102,9 +102,9 @@ package restore

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Restoring instance")
_, err = wait.RestoreInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.BackupId, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Restoring instance", func() error {
_, err = wait.RestoreInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.BackupId, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for MongoDB Flex instance restoration: %w", err)
}
s.Stop()
}

@@ -128,9 +128,9 @@

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Cloning instance")
_, err = wait.CloneInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Cloning instance", func() error {
_, err = wait.CloneInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for MongoDB Flex instance cloning: %w", err)
}
s.Stop()
}

@@ -137,0 +137,0 @@

@@ -124,9 +124,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for MongoDB Flex instance creation: %w", err)
}
s.Stop()
}

@@ -133,0 +133,0 @@

@@ -78,9 +78,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting instance", func() error {
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for MongoDB Flex instance deletion: %w", err)
}
s.Stop()
}

@@ -87,0 +87,0 @@

@@ -110,9 +110,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating instance")
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating instance", func() error {
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for MongoDB Flex instance update: %w", err)
}
s.Stop()
}

@@ -119,0 +119,0 @@

@@ -149,9 +149,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Create network area region")
_, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, *resp.Id, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Create network area region", func() error {
_, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, *resp.Id, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for creating network area region %w", err)
}
s.Stop()
}

@@ -158,0 +158,0 @@ responses.RegionalArea = respNetworkArea

@@ -111,9 +111,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Create network area region")
_, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, model.NetworkAreaId, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Create network area region", func() error {
_, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, model.NetworkAreaId, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for network area region creation: %w", err)
}
s.Stop()
}

@@ -120,0 +120,0 @@

@@ -85,9 +85,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Delete network area region")
_, err = wait.DeleteNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, model.NetworkAreaId, model.Region).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Delete network area region", func() error {
_, err = wait.DeleteNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, model.NetworkAreaId, model.Region).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for network area region deletion: %w", err)
}
s.Stop()
}

@@ -94,0 +94,0 @@

@@ -137,11 +137,10 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating network")
_, err = wait.CreateNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, networkId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating network", func() error {
_, err = wait.CreateNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, networkId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for network creation: %w", err)
}
s.Stop()
}
return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp)

@@ -148,0 +147,0 @@ },

@@ -84,9 +84,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting network")
_, err = wait.DeleteNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.NetworkId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting network", func() error {
_, err = wait.DeleteNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.NetworkId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for network deletion: %w", err)
}
s.Stop()
}

@@ -93,0 +93,0 @@

@@ -118,11 +118,10 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating network")
_, err = wait.UpdateNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, networkId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating network", func() error {
_, err = wait.UpdateNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, networkId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for network update: %w", err)
}
s.Stop()
}
operationState := "Updated"

@@ -129,0 +128,0 @@ if model.Async {

@@ -88,9 +88,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating bucket")
_, err = wait.CreateBucketWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating bucket", func() error {
_, err = wait.CreateBucketWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for Object Storage bucket creation: %w", err)
}
s.Stop()
}

@@ -97,0 +97,0 @@

@@ -70,9 +70,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting bucket")
_, err = wait.DeleteBucketWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting bucket", func() error {
_, err = wait.DeleteBucketWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for Object Storage bucket deletion: %w", err)
}
s.Stop()
}

@@ -79,0 +79,0 @@

@@ -5,2 +5,3 @@ package objectstorage

"github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/bucket"
complianceLock "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/compliance-lock"
"github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials"

@@ -35,2 +36,3 @@ credentialsGroup "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials-group"

cmd.AddCommand(credentials.NewCmd(params))
cmd.AddCommand(complianceLock.NewCmd(params))
}

@@ -97,9 +97,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for Observability instance creation: %w", err)
}
s.Stop()
}

@@ -106,0 +106,0 @@

@@ -78,9 +78,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.InstanceId, model.ProjectId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting instance", func() error {
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.InstanceId, model.ProjectId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for Observability instance deletion: %w", err)
}
s.Stop()
}

@@ -87,0 +87,0 @@

@@ -103,9 +103,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating instance")
_, err = wait.UpdateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating instance", func() error {
_, err = wait.UpdateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for Observability instance update: %w", err)
}
s.Stop()
}

@@ -112,0 +112,0 @@

@@ -109,9 +109,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating scrape config")
_, err = wait.CreateScrapeConfigWaitHandler(ctx, apiClient, model.InstanceId, *jobName, model.ProjectId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating scrape config", func() error {
_, err = wait.CreateScrapeConfigWaitHandler(ctx, apiClient, model.InstanceId, *jobName, model.ProjectId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for scrape configuration creation: %w", err)
}
s.Stop()
}

@@ -118,0 +118,0 @@

@@ -81,9 +81,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting scrape config")
_, err = wait.DeleteScrapeConfigWaitHandler(ctx, apiClient, model.InstanceId, model.JobName, model.ProjectId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting scrape config", func() error {
_, err = wait.DeleteScrapeConfigWaitHandler(ctx, apiClient, model.InstanceId, model.JobName, model.ProjectId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for scrape config deletion: %w", err)
}
s.Stop()
}

@@ -90,0 +90,0 @@

@@ -119,9 +119,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for OpenSearch instance creation: %w", err)
}
s.Stop()
}

@@ -128,0 +128,0 @@

@@ -78,9 +78,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting instance", func() error {
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for OpenSearch instance deletion: %w", err)
}
s.Stop()
}

@@ -87,0 +87,0 @@

@@ -117,9 +117,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating instance")
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating instance", func() error {
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for OpenSearch instance update: %w", err)
}
s.Stop()
}

@@ -126,0 +126,0 @@

@@ -100,9 +100,9 @@ package clone

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Cloning instance")
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Cloning instance", func() error {
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for PostgreSQL Flex instance cloning: %w", err)
}
s.Stop()
}

@@ -109,0 +109,0 @@

@@ -125,9 +125,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for PostgreSQL Flex instance creation: %w", err)
}
s.Stop()
}

@@ -134,0 +134,0 @@

@@ -95,9 +95,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting instance", func() error {
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for PostgreSQL Flex instance deletion: %w", err)
}
s.Stop()
}

@@ -116,9 +116,9 @@ }

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Forcing deletion of instance")
_, err = wait.ForceDeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Forcing deletion of instance", func() error {
_, err = wait.ForceDeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for PostgreSQL Flex instance force deletion: %w", err)
}
s.Stop()
}

@@ -125,0 +125,0 @@ }

@@ -110,9 +110,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating instance")
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating instance", func() error {
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for PostgreSQL Flex instance update: %w", err)
}
s.Stop()
}

@@ -119,0 +119,0 @@

@@ -119,9 +119,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for RabbitMQ instance creation: %w", err)
}
s.Stop()
}

@@ -128,0 +128,0 @@

@@ -78,9 +78,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting instance", func() error {
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for RabbitMQ instance deletion: %w", err)
}
s.Stop()
}

@@ -87,0 +87,0 @@

@@ -117,9 +117,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating instance")
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating instance", func() error {
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for RabbitMQ instance update: %w", err)
}
s.Stop()
}

@@ -126,0 +126,0 @@

@@ -117,9 +117,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating instance")
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating instance", func() error {
_, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for Redis instance creation: %w", err)
}
s.Stop()
}

@@ -126,0 +126,0 @@

@@ -78,9 +78,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting instance")
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting instance", func() error {
_, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for Redis instance deletion: %w", err)
}
s.Stop()
}

@@ -87,0 +87,0 @@

@@ -114,9 +114,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating instance")
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating instance", func() error {
_, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for Redis instance update: %w", err)
}
s.Stop()
}

@@ -123,0 +123,0 @@

@@ -28,2 +28,9 @@ package create

const (
testKmsKeyId = "key-id"
testKmsKeyringId = "keyring-id"
testKmsKeyVersion = int64(1)
testKmsServiceAccountEmail = "my-service-account-1234567@sa.stackit.cloud"
)
func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string {

@@ -167,2 +174,20 @@ flagValues := map[string]string{

{
description: "kms flags",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
delete(flagValues, aclFlag)
flagValues[kmsKeyIdFlag] = testKmsKeyId
flagValues[kmsKeyringIdFlag] = testKmsKeyringId
flagValues[kmsKeyVersionFlag] = "1"
flagValues[kmsServiceAccountEmailFlag] = testKmsServiceAccountEmail
}),
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.Acls = nil
model.KmsKeyId = utils.Ptr(testKmsKeyId)
model.KmsKeyringId = utils.Ptr(testKmsKeyringId)
model.KmsKeyVersion = utils.Ptr(testKmsKeyVersion)
model.KmsServiceAccountEmail = utils.Ptr(testKmsServiceAccountEmail)
}),
},
{
description: "project id missing",

@@ -210,2 +235,24 @@ flagValues: fixtureFlagValues(func(flagValues map[string]string) {

},
{
description: "with kms",
model: fixtureInputModel(func(model *inputModel) {
model.Acls = nil
model.KmsKeyId = utils.Ptr(testKmsKeyId)
model.KmsKeyringId = utils.Ptr(testKmsKeyringId)
model.KmsKeyVersion = utils.Ptr(testKmsKeyVersion)
model.KmsServiceAccountEmail = utils.Ptr(testKmsServiceAccountEmail)
}),
expectedRequest: fixtureRequest(func(request *secretsmanager.ApiCreateInstanceRequest) {
payload := secretsmanager.CreateInstancePayload{
Name: utils.Ptr("example"),
KmsKey: &secretsmanager.KmsKeyPayload{
KeyId: utils.Ptr(testKmsKeyId),
KeyRingId: utils.Ptr(testKmsKeyringId),
KeyVersion: utils.Ptr(testKmsKeyVersion),
ServiceAccountEmail: utils.Ptr(testKmsServiceAccountEmail),
},
}
*request = (*request).CreateInstancePayload(payload)
}),
},
}

@@ -212,0 +259,0 @@

@@ -26,2 +26,7 @@ package create

aclFlag = "acl"
kmsKeyIdFlag = "kms-key-id"
kmsKeyringIdFlag = "kms-keyring-id"
kmsKeyVersionFlag = "kms-key-version"
kmsServiceAccountEmailFlag = "kms-service-account-email"
)

@@ -34,2 +39,7 @@

Acls *[]string
KmsKeyId *string
KmsKeyringId *string
KmsKeyVersion *int64
KmsServiceAccountEmail *string
}

@@ -50,2 +60,5 @@

`$ stackit secrets-manager instance create --name my-instance --acl 1.2.3.0/24`),
examples.NewExample(
`Create a Secrets Manager instance with name "my-instance" and configure KMS key options`,
`$ stackit secrets-manager instance create --name my-instance --kms-key-id key-id --kms-keyring-id keyring-id --kms-key-version 1 --kms-service-account-email my-service-account-1234567@sa.stackit.cloud`),
),

@@ -109,4 +122,11 @@ RunE: func(cmd *cobra.Command, args []string) error {

cmd.Flags().String(kmsKeyIdFlag, "", "ID of the KMS key to use for encryption")
cmd.Flags().String(kmsKeyringIdFlag, "", "ID of the KMS key ring")
cmd.Flags().Int64(kmsKeyVersionFlag, 0, "Version of the KMS key")
cmd.Flags().String(kmsServiceAccountEmailFlag, "", "Service account email for KMS access")
err := flags.MarkFlagsRequired(cmd, instanceNameFlag)
cobra.CheckErr(err)
cmd.MarkFlagsRequiredTogether(kmsKeyIdFlag, kmsKeyringIdFlag, kmsKeyVersionFlag, kmsServiceAccountEmailFlag)
}

@@ -121,5 +141,9 @@

model := inputModel{
GlobalFlagModel: globalFlags,
InstanceName: flags.FlagToStringPointer(p, cmd, instanceNameFlag),
Acls: flags.FlagToStringSlicePointer(p, cmd, aclFlag),
GlobalFlagModel: globalFlags,
InstanceName: flags.FlagToStringPointer(p, cmd, instanceNameFlag),
Acls: flags.FlagToStringSlicePointer(p, cmd, aclFlag),
KmsKeyId: flags.FlagToStringPointer(p, cmd, kmsKeyIdFlag),
KmsKeyringId: flags.FlagToStringPointer(p, cmd, kmsKeyringIdFlag),
KmsKeyVersion: flags.FlagToInt64Pointer(p, cmd, kmsKeyVersionFlag),
KmsServiceAccountEmail: flags.FlagToStringPointer(p, cmd, kmsServiceAccountEmailFlag),
}

@@ -134,6 +158,17 @@

req = req.CreateInstancePayload(secretsmanager.CreateInstancePayload{
payload := secretsmanager.CreateInstancePayload{
Name: model.InstanceName,
})
}
if model.KmsKeyId != nil {
payload.KmsKey = &secretsmanager.KmsKeyPayload{
KeyId: model.KmsKeyId,
KeyRingId: model.KmsKeyringId,
KeyVersion: model.KmsKeyVersion,
ServiceAccountEmail: model.KmsServiceAccountEmail,
}
}
req = req.CreateInstancePayload(payload)
return req

@@ -140,0 +175,0 @@ }

@@ -12,2 +12,3 @@ package describe

"github.com/stackitcloud/stackit-cli/internal/pkg/testutils"
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"

@@ -251,2 +252,17 @@ "github.com/google/go-cmp/cmp"

},
{
name: "instance with kms key",
args: args{
instance: &secretsmanager.Instance{
KmsKey: &secretsmanager.KmsKeyPayload{
KeyId: utils.Ptr("key-id"),
KeyRingId: utils.Ptr("keyring-id"),
KeyVersion: utils.Ptr(int64(1)),
ServiceAccountEmail: utils.Ptr("my-service-account-1234567@sa.stackit.cloud"),
},
},
aclList: &secretsmanager.ListACLsResponse{},
},
wantErr: false,
},
}

@@ -253,0 +269,0 @@ p := print.NewPrinter()

@@ -131,2 +131,13 @@ package describe

table.AddSeparator()
kmsKey := instance.KmsKey
showKms := kmsKey != nil && (kmsKey.KeyId != nil || kmsKey.KeyRingId != nil || kmsKey.KeyVersion != nil || kmsKey.ServiceAccountEmail != nil)
if showKms {
table.AddRow("KMS KEY ID", utils.PtrString(kmsKey.KeyId))
table.AddSeparator()
table.AddRow("KMS KEYRING ID", utils.PtrString(kmsKey.KeyRingId))
table.AddSeparator()
table.AddRow("KMS KEY VERSION", utils.PtrString(kmsKey.KeyVersion))
table.AddSeparator()
table.AddRow("KMS SERVICE ACCOUNT EMAIL", utils.PtrString(kmsKey.ServiceAccountEmail))
}
// Only show ACL if it's present and not empty

@@ -140,2 +151,5 @@ if aclList.Acls != nil && len(*aclList.Acls) > 0 {

if showKms {
table.AddSeparator()
}
table.AddRow("ACL", strings.Join(cidrs, ","))

@@ -142,0 +156,0 @@ }

@@ -7,6 +7,4 @@ package update

"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
"github.com/stackitcloud/stackit-cli/internal/pkg/testutils"
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"

@@ -37,2 +35,10 @@

const (
testInstanceName = "test-instance"
testKmsKeyId = "key-id"
testKmsKeyringId = "keyring-id"
testKmsKeyVersion = int64(1)
testKmsServiceAccountEmail = "my-service-account-1234567@sa.stackit.cloud"
)
func fixtureArgValues(mods ...func(argValues []string)) []string {

@@ -87,2 +93,20 @@ argValues := []string{

func fixtureUpdateInstanceRequest(mods ...func(request *secretsmanager.ApiUpdateInstanceRequest)) secretsmanager.ApiUpdateInstanceRequest {
request := testClient.UpdateInstance(testCtx, testProjectId, testInstanceId)
request = request.UpdateInstancePayload(secretsmanager.UpdateInstancePayload{
Name: utils.Ptr(testInstanceName),
KmsKey: &secretsmanager.KmsKeyPayload{
KeyId: utils.Ptr(testKmsKeyId),
KeyRingId: utils.Ptr(testKmsKeyringId),
KeyVersion: utils.Ptr(testKmsKeyVersion),
ServiceAccountEmail: utils.Ptr(testKmsServiceAccountEmail),
},
})
for _, mod := range mods {
mod(&request)
}
return request
}
func TestParseInput(t *testing.T) {

@@ -117,10 +141,4 @@ tests := []struct {

{
description: "no flag values",
description: "no update flags",
argValues: fixtureArgValues(),
flagValues: map[string]string{},
isValid: false,
},
{
description: "required flags only (no values to update)",
argValues: fixtureArgValues(),
flagValues: map[string]string{

@@ -180,2 +198,23 @@ projectIdFlag: testProjectId,

{
description: "kms key id without other required kms flags",
argValues: fixtureArgValues(),
flagValues: map[string]string{
projectIdFlag: testProjectId,
kmsKeyIdFlag: "key-id",
},
isValid: false,
},
{
description: "kms flags without name flag",
argValues: fixtureArgValues(),
flagValues: map[string]string{
projectIdFlag: testProjectId,
kmsKeyIdFlag: "key-id",
kmsKeyringIdFlag: "keyring-id",
kmsKeyVersionFlag: "1",
kmsServiceAccountEmailFlag: "my-service-account-1234567@sa.stackit.cloud",
},
isValid: false,
},
{
description: "repeated acl flags",

@@ -203,2 +242,70 @@ argValues: fixtureArgValues(),

},
{
description: "name flag only",
argValues: fixtureArgValues(),
flagValues: map[string]string{
projectIdFlag: testProjectId,
instanceNameFlag: "updated-name",
},
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.Acls = nil
model.InstanceName = utils.Ptr("updated-name")
}),
},
{
description: "name and acl flags",
argValues: fixtureArgValues(),
flagValues: map[string]string{
projectIdFlag: testProjectId,
instanceNameFlag: testInstanceName,
aclFlag: testACL1,
},
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.InstanceName = utils.Ptr(testInstanceName)
}),
},
{
description: "kms flags with name",
argValues: fixtureArgValues(),
flagValues: map[string]string{
projectIdFlag: testProjectId,
instanceNameFlag: testInstanceName,
kmsKeyIdFlag: testKmsKeyId,
kmsKeyringIdFlag: testKmsKeyringId,
kmsKeyVersionFlag: "1",
kmsServiceAccountEmailFlag: testKmsServiceAccountEmail,
},
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.Acls = nil
model.InstanceName = utils.Ptr(testInstanceName)
model.KmsKeyId = utils.Ptr(testKmsKeyId)
model.KmsKeyringId = utils.Ptr(testKmsKeyringId)
model.KmsKeyVersion = utils.Ptr(testKmsKeyVersion)
model.KmsServiceAccountEmail = utils.Ptr(testKmsServiceAccountEmail)
}),
},
{
description: "name, acl and kms flags together",
argValues: fixtureArgValues(),
flagValues: map[string]string{
projectIdFlag: testProjectId,
instanceNameFlag: testInstanceName,
aclFlag: testACL1,
kmsKeyIdFlag: testKmsKeyId,
kmsKeyringIdFlag: testKmsKeyringId,
kmsKeyVersionFlag: "1",
kmsServiceAccountEmailFlag: testKmsServiceAccountEmail,
},
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.InstanceName = utils.Ptr(testInstanceName)
model.KmsKeyId = utils.Ptr(testKmsKeyId)
model.KmsKeyringId = utils.Ptr(testKmsKeyringId)
model.KmsKeyVersion = utils.Ptr(testKmsKeyVersion)
model.KmsServiceAccountEmail = utils.Ptr(testKmsServiceAccountEmail)
}),
},
}

@@ -208,64 +315,9 @@

t.Run(tt.description, func(t *testing.T) {
p := print.NewPrinter()
cmd := NewCmd(&types.CmdParams{Printer: p})
err := globalflags.Configure(cmd.Flags())
if err != nil {
t.Fatalf("configure global flags: %v", err)
}
for flag, value := range tt.flagValues {
err := cmd.Flags().Set(flag, value)
if err != nil {
if !tt.isValid {
return
}
t.Fatalf("setting flag --%s=%s: %v", flag, value, err)
}
}
for _, value := range tt.aclValues {
err := cmd.Flags().Set(aclFlag, value)
if err != nil {
if !tt.isValid {
return
}
t.Fatalf("setting flag --%s=%s: %v", aclFlag, value, err)
}
}
err = cmd.ValidateArgs(tt.argValues)
if err != nil {
if !tt.isValid {
return
}
t.Fatalf("error validating args: %v", err)
}
err = cmd.ValidateRequiredFlags()
if err != nil {
if !tt.isValid {
return
}
t.Fatalf("error validating flags: %v", err)
}
model, err := parseInput(p, cmd, tt.argValues)
if err != nil {
if !tt.isValid {
return
}
t.Fatalf("error parsing flags: %v", err)
}
if !tt.isValid {
t.Fatalf("did not fail on invalid input")
}
diff := cmp.Diff(model, tt.expectedModel)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
testutils.TestParseInputWithAdditionalFlags(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, map[string][]string{
aclFlag: tt.aclValues,
}, tt.isValid)
})
}
}
func TestBuildRequest(t *testing.T) {
func TestBuildUpdateACLsRequest(t *testing.T) {
tests := []struct {

@@ -296,3 +348,3 @@ description string

t.Run(tt.description, func(t *testing.T) {
request := buildRequest(testCtx, tt.model, testClient)
request := buildUpdateACLsRequest(testCtx, tt.model, testClient)

@@ -309,1 +361,47 @@ diff := cmp.Diff(request, tt.expectedRequest,

}
func TestBuildUpdateInstanceRequest(t *testing.T) {
tests := []struct {
description string
model *inputModel
expectedRequest secretsmanager.ApiUpdateInstanceRequest
}{
{
description: "with name only",
model: fixtureInputModel(func(model *inputModel) {
model.Acls = nil
model.InstanceName = utils.Ptr(testInstanceName)
}),
expectedRequest: testClient.UpdateInstance(testCtx, testProjectId, testInstanceId).
UpdateInstancePayload(secretsmanager.UpdateInstancePayload{
Name: utils.Ptr(testInstanceName),
}),
},
{
description: "with KMS settings",
model: fixtureInputModel(func(model *inputModel) {
model.Acls = nil
model.InstanceName = utils.Ptr(testInstanceName)
model.KmsKeyId = utils.Ptr(testKmsKeyId)
model.KmsKeyringId = utils.Ptr(testKmsKeyringId)
model.KmsKeyVersion = utils.Ptr(testKmsKeyVersion)
model.KmsServiceAccountEmail = utils.Ptr(testKmsServiceAccountEmail)
}),
expectedRequest: fixtureUpdateInstanceRequest(),
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
request := buildUpdateInstanceRequest(testCtx, tt.model, testClient)
diff := cmp.Diff(request, tt.expectedRequest,
cmp.AllowUnexported(tt.expectedRequest),
cmpopts.EquateComparable(testCtx),
)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
})
}
}

@@ -27,3 +27,9 @@ package update

aclFlag = "acl"
instanceNameFlag = "name"
aclFlag = "acl"
kmsKeyIdFlag = "kms-key-id"
kmsKeyringIdFlag = "kms-keyring-id"
kmsKeyVersionFlag = "kms-key-version"
kmsServiceAccountEmailFlag = "kms-service-account-email"
)

@@ -35,3 +41,9 @@

Acls *[]string
InstanceName *string
Acls *[]string
KmsKeyId *string
KmsKeyringId *string
KmsKeyVersion *int64
KmsServiceAccountEmail *string
}

@@ -47,4 +59,13 @@

examples.NewExample(
`Update the name of a Secrets Manager instance with ID "xxx"`,
"$ stackit secrets-manager instance update xxx --name my-new-name"),
examples.NewExample(
`Update the range of IPs allowed to access a Secrets Manager instance with ID "xxx"`,
"$ stackit secrets-manager instance update xxx --acl 1.2.3.0/24"),
examples.NewExample(
`Update the name and ACLs of a Secrets Manager instance with ID "xxx"`,
"$ stackit secrets-manager instance update xxx --name my-new-name --acl 1.2.3.0/24"),
examples.NewExample(
`Update the KMS key settings of a Secrets Manager instance with ID "xxx"`,
"$ stackit secrets-manager instance update xxx --name my-instance --kms-key-id key-id --kms-keyring-id keyring-id --kms-key-version 1 --kms-service-account-email my-service-account-1234567@sa.stackit.cloud"),
),

@@ -64,9 +85,9 @@ RunE: func(cmd *cobra.Command, args []string) error {

instanceLabel, err := secretsManagerUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId)
existingInstanceName, err := secretsManagerUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId)
if err != nil {
params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err)
instanceLabel = model.InstanceId
existingInstanceName = model.InstanceId
}
prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel)
prompt := fmt.Sprintf("Are you sure you want to update instance %q?", existingInstanceName)
err = params.Printer.PromptForConfirmation(prompt)

@@ -77,10 +98,26 @@ if err != nil {

// Call API
req := buildRequest(ctx, model, apiClient)
err = req.Execute()
if err != nil {
return fmt.Errorf("update Secrets Manager instance: %w", err)
// Call API - execute UpdateInstance and/or UpdateACLs based on flags
if model.InstanceName != nil {
req := buildUpdateInstanceRequest(ctx, model, apiClient)
err = req.Execute()
if err != nil {
return fmt.Errorf("update Secrets Manager instance: %w", err)
}
}
params.Printer.Info("Updated instance %q\n", instanceLabel)
if model.Acls != nil {
req := buildUpdateACLsRequest(ctx, model, apiClient)
err = req.Execute()
if err != nil {
if model.InstanceName != nil {
return fmt.Errorf(`the Secrets Manager instance was successfully updated, but the configuration of the ACLs failed.
If you want to retry configuring the ACLs, you can do it via:
$ stackit secrets-manager instance update %s --acl %s`, model.InstanceId, *model.Acls)
}
return fmt.Errorf("update Secrets Manager instance ACLs: %w", err)
}
}
params.Printer.Info("Updated instance %q\n", existingInstanceName)
return nil

@@ -94,3 +131,12 @@ },

func configureFlags(cmd *cobra.Command) {
cmd.Flags().StringP(instanceNameFlag, "n", "", "Instance name")
cmd.Flags().Var(flags.CIDRSliceFlag(), aclFlag, "List of IP networks in CIDR notation which are allowed to access this instance")
cmd.Flags().String(kmsKeyIdFlag, "", "ID of the KMS key to use for encryption")
cmd.Flags().String(kmsKeyringIdFlag, "", "ID of the KMS key ring")
cmd.Flags().Int64(kmsKeyVersionFlag, 0, "Version of the KMS key")
cmd.Flags().String(kmsServiceAccountEmailFlag, "", "Service account email for KMS access")
cmd.MarkFlagsRequiredTogether(kmsKeyIdFlag, kmsKeyringIdFlag, kmsKeyVersionFlag, kmsServiceAccountEmailFlag)
cmd.MarkFlagsOneRequired(aclFlag, instanceNameFlag)
}

@@ -106,12 +152,15 @@

acls := flags.FlagToStringSlicePointer(p, cmd, aclFlag)
if acls == nil {
return nil, &cliErr.EmptyUpdateError{}
model := inputModel{
GlobalFlagModel: globalFlags,
InstanceId: instanceId,
InstanceName: flags.FlagToStringPointer(p, cmd, instanceNameFlag),
Acls: flags.FlagToStringSlicePointer(p, cmd, aclFlag),
KmsKeyId: flags.FlagToStringPointer(p, cmd, kmsKeyIdFlag),
KmsKeyringId: flags.FlagToStringPointer(p, cmd, kmsKeyringIdFlag),
KmsKeyVersion: flags.FlagToInt64Pointer(p, cmd, kmsKeyVersionFlag),
KmsServiceAccountEmail: flags.FlagToStringPointer(p, cmd, kmsServiceAccountEmailFlag),
}
model := inputModel{
GlobalFlagModel: globalFlags,
InstanceId: instanceId,
Acls: acls,
if model.KmsKeyId != nil && model.InstanceName == nil {
return nil, fmt.Errorf("--name is required when using KMS flags")
}

@@ -123,3 +172,24 @@

func buildRequest(ctx context.Context, model *inputModel, apiClient *secretsmanager.APIClient) secretsmanager.ApiUpdateACLsRequest {
func buildUpdateInstanceRequest(ctx context.Context, model *inputModel, apiClient *secretsmanager.APIClient) secretsmanager.ApiUpdateInstanceRequest {
req := apiClient.UpdateInstance(ctx, model.ProjectId, model.InstanceId)
payload := secretsmanager.UpdateInstancePayload{
Name: model.InstanceName,
}
if model.KmsKeyId != nil {
payload.KmsKey = &secretsmanager.KmsKeyPayload{
KeyId: model.KmsKeyId,
KeyRingId: model.KmsKeyringId,
KeyVersion: model.KmsKeyVersion,
ServiceAccountEmail: model.KmsServiceAccountEmail,
}
}
req = req.UpdateInstancePayload(payload)
return req
}
func buildUpdateACLsRequest(ctx context.Context, model *inputModel, apiClient *secretsmanager.APIClient) secretsmanager.ApiUpdateACLsRequest {
req := apiClient.UpdateACLs(ctx, model.ProjectId, model.InstanceId)

@@ -126,0 +196,0 @@

@@ -147,9 +147,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating server")
_, err = wait.CreateServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, serverId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating server", func() error {
_, err = wait.CreateServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, serverId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for server creation: %w", err)
}
s.Stop()
}

@@ -156,0 +156,0 @@

@@ -81,9 +81,9 @@ package deallocate

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deallocating server")
_, err = wait.DeallocateServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deallocating server", func() error {
_, err = wait.DeallocateServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for server deallocating: %w", err)
}
s.Stop()
}

@@ -90,0 +90,0 @@

@@ -8,3 +8,5 @@ package delete

"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/stackitcloud/stackit-sdk-go/services/iaas/wait"
"github.com/spf13/cobra"
"github.com/stackitcloud/stackit-cli/internal/pkg/args"

@@ -20,5 +22,2 @@ "github.com/stackitcloud/stackit-cli/internal/pkg/errors"

"github.com/stackitcloud/stackit-sdk-go/services/iaas"
"github.com/stackitcloud/stackit-sdk-go/services/iaas/wait"
"github.com/spf13/cobra"
)

@@ -86,9 +85,9 @@

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting server")
_, err = wait.DeleteServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting server", func() error {
_, err = wait.DeleteServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for server deletion: %w", err)
}
s.Stop()
}

@@ -95,0 +94,0 @@

@@ -85,9 +85,9 @@ package rescue

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Rescuing server")
_, err = wait.RescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Rescuing server", func() error {
_, err = wait.RescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for server rescuing: %w", err)
}
s.Stop()
}

@@ -94,0 +94,0 @@

@@ -85,9 +85,9 @@ package resize

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Resizing server")
_, err = wait.ResizeServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Resizing server", func() error {
_, err = wait.ResizeServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for server resizing: %w", err)
}
s.Stop()
}

@@ -94,0 +94,0 @@

@@ -75,9 +75,9 @@ package start

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Starting server")
_, err = wait.StartServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Starting server", func() error {
_, err = wait.StartServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for server starting: %w", err)
}
s.Stop()
}

@@ -84,0 +84,0 @@

@@ -81,9 +81,9 @@ package stop

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Stopping server")
_, err = wait.StopServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Stopping server", func() error {
_, err = wait.StopServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for server stopping: %w", err)
}
s.Stop()
}

@@ -90,0 +90,0 @@

@@ -81,9 +81,9 @@ package unrescue

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Unrescuing server")
_, err = wait.UnrescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Unrescuing server", func() error {
_, err = wait.UnrescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for server unrescuing: %w", err)
}
s.Stop()
}

@@ -90,0 +90,0 @@

@@ -136,9 +136,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating cluster")
_, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, name).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating cluster", func() error {
_, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, name).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SKE cluster creation: %w", err)
}
s.Stop()
}

@@ -145,0 +145,0 @@

@@ -70,9 +70,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting cluster")
_, err = wait.DeleteClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting cluster", func() error {
_, err = wait.DeleteClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SKE cluster deletion: %w", err)
}
s.Stop()
}

@@ -79,0 +79,0 @@

@@ -19,3 +19,3 @@ package hibernate

ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api"
wait "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api/wait"
"github.com/stackitcloud/stackit-sdk-go/services/ske/v2api/wait"
)

@@ -76,9 +76,9 @@

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Hibernating cluster")
_, err = wait.TriggerClusterHibernationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Hibernating cluster", func() error {
_, err = wait.TriggerClusterHibernationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SKE cluster hibernation: %w", err)
}
s.Stop()
}

@@ -85,0 +85,0 @@

@@ -75,9 +75,9 @@ package maintenance

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Performing cluster maintenance")
_, err = wait.TriggerClusterMaintenanceWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Performing cluster maintenance", func() error {
_, err = wait.TriggerClusterMaintenanceWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SKE cluster maintenance to complete: %w", err)
}
s.Stop()
}

@@ -84,0 +84,0 @@

@@ -63,9 +63,9 @@ package reconcile

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Performing cluster reconciliation")
_, err = wait.TriggerClusterReconciliationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Performing cluster reconciliation", func() error {
_, err = wait.TriggerClusterReconciliationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SKE cluster reconciliation: %w", err)
}
s.Stop()
}

@@ -72,0 +72,0 @@

@@ -98,9 +98,9 @@ package update

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Updating cluster")
_, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, name).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Updating cluster", func() error {
_, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, name).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SKE cluster update: %w", err)
}
s.Stop()
}

@@ -107,0 +107,0 @@

@@ -63,9 +63,9 @@ package wakeup

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Performing cluster wakeup")
_, err = wait.TriggerClusterWakeupWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Performing cluster wakeup", func() error {
_, err = wait.TriggerClusterWakeupWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SKE cluster wakeup: %w", err)
}
s.Stop()
}

@@ -72,0 +72,0 @@

@@ -87,9 +87,9 @@ package completerotation

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Completing credentials rotation")
_, err = wait.CompleteCredentialsRotationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Completing credentials rotation", func() error {
_, err = wait.CompleteCredentialsRotationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for completing SKE credentials rotation %w", err)
}
s.Stop()
}

@@ -96,0 +96,0 @@

@@ -90,9 +90,9 @@ package startrotation

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Starting credentials rotation")
_, err = wait.StartCredentialsRotationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Starting credentials rotation", func() error {
_, err = wait.StartCredentialsRotationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for start SKE credentials rotation %w", err)
}
s.Stop()
}

@@ -99,0 +99,0 @@

@@ -73,9 +73,9 @@ package disable

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Disabling SKE")
_, err = wait.DisableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Disabling SKE", func() error {
_, err = wait.DisableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SKE disabling: %w", err)
}
s.Stop()
}

@@ -82,0 +82,0 @@

@@ -73,9 +73,9 @@ package enable

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Enabling SKE")
_, err = wait.EnableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Enabling SKE", func() error {
_, err = wait.EnableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for SKE enabling: %w", err)
}
s.Stop()
}

@@ -82,0 +82,0 @@

@@ -118,9 +118,8 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating backup")
resp, err = wait.CreateBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, volumeId).WaitWithContext(ctx)
resp, err = spinner.Run2(params.Printer, "Creating backup", func() (*iaas.Backup, error) {
return wait.CreateBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, volumeId).WaitWithContext(ctx)
})
if err != nil {
return fmt.Errorf("wait for backup creation: %w", err)
}
s.Stop()
}

@@ -127,0 +126,0 @@

@@ -76,9 +76,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting backup")
_, err = wait.DeleteBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BackupId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting backup", func() error {
_, err = wait.DeleteBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BackupId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for backup deletion: %w", err)
}
s.Stop()
}

@@ -85,0 +85,0 @@

@@ -89,9 +89,9 @@ package restore

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Restoring backup")
_, err = wait.RestoreBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BackupId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Restoring backup", func() error {
_, err = wait.RestoreBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BackupId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for backup restore: %w", err)
}
s.Stop()
}

@@ -98,0 +98,0 @@

@@ -107,9 +107,9 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating volume")
_, err = wait.CreateVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, volumeId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Creating volume", func() error {
_, err = wait.CreateVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, volumeId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for volume creation: %w", err)
}
s.Stop()
}

@@ -116,0 +116,0 @@

@@ -82,9 +82,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting volume")
_, err = wait.DeleteVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting volume", func() error {
_, err = wait.DeleteVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for volume deletion: %w", err)
}
s.Stop()
}

@@ -91,0 +91,0 @@

@@ -97,9 +97,8 @@ package create

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Creating snapshot")
resp, err = wait.CreateSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Id).WaitWithContext(ctx)
resp, err = spinner.Run2(params.Printer, "Creating snapshot", func() (*iaas.Snapshot, error) {
return wait.CreateSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Id).WaitWithContext(ctx)
})
if err != nil {
return fmt.Errorf("wait for snapshot creation: %w", err)
}
s.Stop()
}

@@ -106,0 +105,0 @@

@@ -79,9 +79,9 @@ package delete

if !model.Async {
s := spinner.New(params.Printer)
s.Start("Deleting snapshot")
_, err = wait.DeleteSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.SnapshotId).WaitWithContext(ctx)
err := spinner.Run(params.Printer, "Deleting snapshot", func() error {
_, err = wait.DeleteSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.SnapshotId).WaitWithContext(ctx)
return err
})
if err != nil {
return fmt.Errorf("wait for snapshot deletion: %w", err)
}
s.Stop()
}

@@ -88,0 +88,0 @@

@@ -345,3 +345,3 @@ package auth

switch runtime.GOOS {
case "linux":
case "freebsd", "linux":
// We need to use the windows way on WSL, otherwise we do not pass query

@@ -348,0 +348,0 @@ // parameters correctly. https://github.com/microsoft/WSL/issues/3832

@@ -18,3 +18,26 @@ package spinner

func New(p *print.Printer) *Spinner {
// Run starts a spinner and stops it when f completes
func Run(p *print.Printer, message string, f func() error) error {
_, err := Run2(p, message, func() (struct{}, error) {
err := f()
return struct{}{}, err
})
return err
}
// Run2 starts a spinner and stops it when f (result arity 2) completes.
func Run2[T any](p *print.Printer, message string, f func() (T, error)) (T, error) {
var r T
spinner := newSpinner(p)
spinner.start(message)
r, err := f()
if err != nil {
spinner.stopWithError()
return r, err
}
spinner.stop()
return r, nil
}
func newSpinner(p *print.Printer) *Spinner {
return &Spinner{

@@ -29,3 +52,3 @@ printer: p,

func (s *Spinner) Start(message string) {
func (s *Spinner) start(message string) {
s.message = message

@@ -35,3 +58,3 @@ go s.animate()

func (s *Spinner) Stop() {
func (s *Spinner) stop() {
s.done <- true

@@ -42,3 +65,3 @@ close(s.done)

func (s *Spinner) StopWithError() {
func (s *Spinner) stopWithError() {
s.done <- true

@@ -45,0 +68,0 @@ close(s.done)