mygithub.libinneed.workers.dev/stackitcloud/stackit-cli
Advanced tools
| ## 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 | ||
| } |
@@ -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 |
@@ -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) |