diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index 37e166f19..a896082e6 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -74,7 +74,7 @@ type inputModel struct { } // "bar" command constructor -func NewCmd() *cobra.Command { +func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "bar", Short: "Short description of the command (is shown in the help of parent command)", @@ -88,13 +88,13 @@ func NewCmd() *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(cmd, args) + model, err := parseInput(p, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(cmd) + apiClient, err := client.ConfigureClient(p, cmd) if err != nil { return err } @@ -106,7 +106,7 @@ func NewCmd() *cobra.Command { return fmt.Errorf("(...): %w", err) } - projectLabel, err := projectname.GetProjectName(ctx, cmd) + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) if err != nil { projectLabel = model.ProjectId } @@ -116,7 +116,7 @@ func NewCmd() *cobra.Command { p.Info("(...)", projectLabel) return nil } - return outputResult(cmd, model.OutputFormat, instances) + return outputResult(p, cmd, model.OutputFormat, instances) }, } @@ -152,9 +152,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *foo.APIClie } // Output result based on the configured output format -func outputResult(cmd *cobra.Command, outputFormat string, resources []foo.Resource) error { +func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, resources []foo.Resource) error { switch outputFormat { - case globalflags.JSONOutputFormat: + case print.JSONOutputFormat: details, err := json.MarshalIndent(resources, "", " ") if err != nil { return fmt.Errorf("marshal resource list: %w", err) @@ -177,7 +177,7 @@ func outputResult(cmd *cobra.Command, outputFormat string, resources []foo.Resou } ``` -Please remeber to always add unit tests for `parseInput`, `buildRequest` (in `bar_test.go`), and any other util functions used. +Please remember to always add unit tests for `parseInput`, `buildRequest` (in `bar_test.go`), and any other util functions used. If the new command `bar` is the first command in the CLI using a STACKIT service `foo`, please refer to [Onboarding a new STACKIT service](./CONTRIBUTION.md/#onboarding-a-new-stackit-service). diff --git a/internal/cmd/argus/instance/create/create.go b/internal/cmd/argus/instance/create/create.go index 245097b49..4e614fbb5 100644 --- a/internal/cmd/argus/instance/create/create.go +++ b/internal/cmd/argus/instance/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "errors" "fmt" @@ -102,12 +103,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) - return nil + return outputResult(p, model, projectLabel, resp) }, } configureFlags(cmd) @@ -190,3 +186,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient argusClient) }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *argus.CreateInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal Argus instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, *resp.InstanceId) + return nil + } +} diff --git a/internal/cmd/config/list/list.go b/internal/cmd/config/list/list.go index 0f6974703..3da8eb0a1 100644 --- a/internal/cmd/config/list/list.go +++ b/internal/cmd/config/list/list.go @@ -1,7 +1,9 @@ package list import ( + "encoding/json" "fmt" + "slices" "sort" "strconv" @@ -10,6 +12,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "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/tables" @@ -17,6 +20,10 @@ import ( "github.com/spf13/viper" ) +type inputModel struct { + *globalflags.GlobalFlagModel +} + func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "list", @@ -35,56 +42,82 @@ func NewCmd(p *print.Printer) *cobra.Command { examples.NewExample( `List your active configuration`, "$ stackit config list"), + examples.NewExample( + `List your active configuration in a json format`, + "$ stackit config list --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { configData := viper.AllSettings() - // Sort the config options by key - configKeys := make([]string, 0, len(configData)) - for k := range configData { - configKeys = append(configKeys, k) - } - sort.Strings(configKeys) + model := parseInput(p, cmd) + return outputResult(p, model.OutputFormat, configData) + }, + } + return cmd +} - table := tables.NewTable() - table.SetHeader("NAME", "VALUE") - for _, key := range configKeys { - value := configData[key] +func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { + globalFlags := globalflags.Parse(p, cmd) - // Convert value to string - // (Assuming value is either string or bool) - valueString, ok := value.(string) - if !ok { - valueBool, ok := value.(bool) - if !ok { - continue - } - valueString = strconv.FormatBool(valueBool) - } + return &inputModel{ + GlobalFlagModel: globalFlags, + } +} - // Don't show unset values - if valueString == "" { - continue - } +func outputResult(p *print.Printer, outputFormat string, configData map[string]any) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(configData, "", " ") + if err != nil { + return fmt.Errorf("marshal config list: %w", err) + } + p.Outputln(string(details)) + return nil + default: + // Sort the config options by key + configKeys := make([]string, 0, len(configData)) + for k := range configData { + configKeys = append(configKeys, k) + } + sort.Strings(configKeys) - // Don't show unsupported (deprecated or user-inputted) configuration options - // that might be present in the config file - if !slices.Contains(config.ConfigKeys, key) { + table := tables.NewTable() + table.SetHeader("NAME", "VALUE") + for _, key := range configKeys { + value := configData[key] + + // Convert value to string + // (Assuming value is either string or bool) + valueString, ok := value.(string) + if !ok { + valueBool, ok := value.(bool) + if !ok { continue } + valueString = strconv.FormatBool(valueBool) + } - // Replace "_" with "-" to match the flags - key = strings.ReplaceAll(key, "_", "-") - - table.AddRow(key, valueString) - table.AddSeparator() + // Don't show unset values + if valueString == "" { + continue } - err := table.Display(p) - if err != nil { - return fmt.Errorf("render table: %w", err) + + // Don't show unsupported (deprecated or user-inputted) configuration options + // that might be present in the config file + if !slices.Contains(config.ConfigKeys, key) { + continue } - return nil - }, + + // Replace "_" with "-" to match the flags + key = strings.ReplaceAll(key, "_", "-") + + table.AddRow(key, valueString) + table.AddSeparator() + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil } - return cmd } diff --git a/internal/cmd/curl/curl.go b/internal/cmd/curl/curl.go index 694261d4e..292effffc 100644 --- a/internal/cmd/curl/curl.go +++ b/internal/cmd/curl/curl.go @@ -212,7 +212,7 @@ func outputResponse(p *print.Printer, model *inputModel, resp *http.Response) er } respBody, err := io.ReadAll(resp.Body) if err != nil { - return fmt.Errorf("read respose body: %w", err) + return fmt.Errorf("read response body: %w", err) } output = append(output, respBody...) diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 7d3fbbd4e..c7828440e 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -98,12 +99,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s record set for zone %s. Record set ID: %s\n", operationState, zoneLabel, recordSetId) - return nil + return outputResult(p, model, zoneLabel, resp) }, } configureFlags(cmd) @@ -157,3 +153,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *dns.APIClie }) return req } + +func outputResult(p *print.Printer, model *inputModel, zoneLabel string, resp *dns.RecordSetResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal DNS record-set: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s record set for zone %s. Record set ID: %s\n", operationState, zoneLabel, *resp.Rrset.Id) + return nil + } +} diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index abe905bee..733f6a836 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -112,12 +113,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s zone for project %q. Zone ID: %s\n", operationState, projectLabel, zoneId) - return nil + return outputResult(p, model, projectLabel, resp) }, } configureFlags(cmd) @@ -186,3 +182,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *dns.APIClie }) return req } + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *dns.ZoneResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal DNS zone: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s zone for project %q. Zone ID: %s\n", operationState, projectLabel, *resp.Zone.Id) + return nil + } +} diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index 7120d721f..b01f98b1a 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -76,21 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create LogMe credentials: %w", err) } - p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) - // The username field cannot be set by the user so we only display it if it's not returned empty - username := *resp.Raw.Credentials.Username - if username != "" { - p.Outputf("Username: %s\n", *resp.Raw.Credentials.Username) - } - if model.HidePassword { - p.Outputf("Password: \n") - } else { - p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) - } - p.Outputf("Host: %s\n", *resp.Raw.Credentials.Host) - p.Outputf("Port: %d\n", *resp.Raw.Credentials.Port) - p.Outputf("URI: %s\n", *resp.Uri) - return nil + return outputResult(p, model, instanceLabel, resp) }, } configureFlags(cmd) @@ -122,3 +109,32 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *logme.APICl req := apiClient.CreateCredentials(ctx, model.ProjectId, model.InstanceId) return req } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *logme.CredentialsResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal LogMe credentials: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) + // The username field cannot be set by the user so we only display it if it's not returned empty + username := *resp.Raw.Credentials.Username + if username != "" { + p.Outputf("Username: %s\n", *resp.Raw.Credentials.Username) + } + if model.HidePassword { + p.Outputf("Password: \n") + } else { + p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) + } + p.Outputf("Host: %s\n", *resp.Raw.Credentials.Host) + p.Outputf("Port: %d\n", *resp.Raw.Credentials.Port) + p.Outputf("URI: %s\n", *resp.Uri) + return nil + } +} diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index 472eb4f0e..92caf7e85 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "errors" "fmt" "strings" @@ -123,12 +124,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) - return nil + return outputResult(p, model, projectLabel, resp) }, } configureFlags(cmd) @@ -242,3 +238,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient logMeClient) }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *logme.CreateInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal LogMe instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, *resp.InstanceId) + return nil + } +} diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 122bef421..838a44380 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -76,21 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create MariaDB credentials: %w", err) } - p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) - // The username field cannot be set by the user so we only display it if it's not returned empty - username := *resp.Raw.Credentials.Username - if username != "" { - p.Outputf("Username: %s\n", *resp.Raw.Credentials.Username) - } - if model.HidePassword { - p.Outputf("Password: \n") - } else { - p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) - } - p.Outputf("Host: %s\n", *resp.Raw.Credentials.Host) - p.Outputf("Port: %d\n", *resp.Raw.Credentials.Port) - p.Outputf("URI: %s\n", *resp.Uri) - return nil + return outputResult(p, model, instanceLabel, resp) }, } configureFlags(cmd) @@ -122,3 +109,32 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mariadb.API req := apiClient.CreateCredentials(ctx, model.ProjectId, model.InstanceId) return req } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *mariadb.CredentialsResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal MariaDB credentials: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) + // The username field cannot be set by the user so we only display it if it's not returned empty + username := *resp.Raw.Credentials.Username + if username != "" { + p.Outputf("Username: %s\n", *resp.Raw.Credentials.Username) + } + if model.HidePassword { + p.Outputf("Password: \n") + } else { + p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) + } + p.Outputf("Host: %s\n", *resp.Raw.Credentials.Host) + p.Outputf("Port: %d\n", *resp.Raw.Credentials.Port) + p.Outputf("URI: %s\n", *resp.Uri) + return nil + } +} diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index 2b0b4e3ef..c2e2fd07d 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "errors" "fmt" "strings" @@ -123,12 +124,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) - return nil + return outputResult(p, model, projectLabel, resp) }, } configureFlags(cmd) @@ -242,3 +238,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient mariaDBClien }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *mariadb.CreateInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal MariaDB instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, *resp.InstanceId) + return nil + } +} diff --git a/internal/cmd/mariadb/instance/update/update.go b/internal/cmd/mariadb/instance/update/update.go index f22ae7863..d2c857d4a 100644 --- a/internal/cmd/mariadb/instance/update/update.go +++ b/internal/cmd/mariadb/instance/update/update.go @@ -25,7 +25,6 @@ import ( const ( instanceIdArg = "INSTANCE_ID" - instanceNameFlag = "name" enableMonitoringFlag = "enable-monitoring" graphiteFlag = "graphite" metricsFrequencyFlag = "metrics-frequency" diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index 91b2178f8..fbce76df9 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "errors" "fmt" @@ -131,12 +132,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) - return nil + return outputResult(p, model, projectLabel, resp) }, } configureFlags(cmd) @@ -264,3 +260,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient MongoDBFlexC }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *mongodbflex.CreateInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal MongoDBFlex instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, *resp.Id) + return nil + } +} diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index 69ae210d5..a559ef2d1 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -2,6 +2,7 @@ package update import ( "context" + "encoding/json" "errors" "fmt" @@ -116,12 +117,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Updated" - if model.Async { - operationState = "Triggered update of" - } - p.Info("%s instance %q\n", operationState, instanceLabel) - return nil + return outputResult(p, model, instanceLabel, resp) }, } configureFlags(cmd) @@ -298,3 +294,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient MongoDBFlexC }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *mongodbflex.UpdateInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal update MongoDBFlex instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Updated" + if model.Async { + operationState = "Triggered update of" + } + p.Info("%s instance %q\n", operationState, instanceLabel) + return nil + } +} diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index 27825a5f0..43b20982b 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -2,8 +2,10 @@ package create import ( "context" + "encoding/json" "fmt" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -12,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/client" mongodbflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/utils" - - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -91,16 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } user := resp.Item - p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, *user.Id) - p.Outputf("Username: %s\n", *user.Username) - p.Outputf("Password: %s\n", *user.Password) - p.Outputf("Roles: %v\n", *user.Roles) - p.Outputf("Database: %s\n", *user.Database) - p.Outputf("Host: %s\n", *user.Host) - p.Outputf("Port: %d\n", *user.Port) - p.Outputf("URI: %s\n", *user.Uri) - - return nil + return outputResult(p, model, instanceLabel, user) }, } @@ -144,3 +135,27 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex }) return req } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, user *mongodbflex.User) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(user, "", " ") + if err != nil { + return fmt.Errorf("marshal MongoDB Flex user: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, *user.Id) + p.Outputf("Username: %s\n", *user.Username) + p.Outputf("Password: %s\n", *user.Password) + p.Outputf("Roles: %v\n", *user.Roles) + p.Outputf("Database: %s\n", *user.Database) + p.Outputf("Host: %s\n", *user.Host) + p.Outputf("Port: %d\n", *user.Port) + p.Outputf("URI: %s\n", *user.Uri) + + return nil + } +} diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password.go b/internal/cmd/mongodbflex/user/reset-password/reset_password.go index c9e60ec13..169e10141 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -2,6 +2,7 @@ package resetpassword import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -85,11 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("reset MongoDB Flex user password: %w", err) } - p.Outputf("Reset password for user %q of instance %q\n\n", userLabel, instanceLabel) - p.Outputf("Username: %s\n", *user.Username) - p.Outputf("New password: %s\n", *user.Password) - p.Outputf("New URI: %s\n", *user.Uri) - return nil + return outputResult(p, model, userLabel, instanceLabel, user) }, } @@ -123,3 +120,22 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex req := apiClient.ResetUser(ctx, model.ProjectId, model.InstanceId, model.UserId) return req } + +func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel string, user *mongodbflex.User) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(user, "", " ") + if err != nil { + return fmt.Errorf("marshal MongoDB Flex reset password: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Reset password for user %q of instance %q\n\n", userLabel, instanceLabel) + p.Outputf("Username: %s\n", *user.Username) + p.Outputf("New password: %s\n", *user.Password) + p.Outputf("New URI: %s\n", *user.Uri) + return nil + } +} diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index 9409f257f..ab5836949 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -60,7 +61,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Call API req := buildRequest(ctx, model, apiClient) - _, err = req.Execute() + resp, err := req.Execute() if err != nil { return fmt.Errorf("create Object Storage bucket: %w", err) } @@ -76,12 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s bucket %q\n", operationState, model.BucketName) - return nil + return outputResult(p, model, resp) }, } return cmd @@ -105,3 +101,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora req := apiClient.CreateBucket(ctx, model.ProjectId, model.BucketName) return req } + +func outputResult(p *print.Printer, model *inputModel, resp *objectstorage.CreateBucketResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal Object Storage bucket: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s bucket %q\n", operationState, model.BucketName) + return nil + } +} diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index 1400289b5..267ca7fb0 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -65,9 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Object Storage credentials group: %w", err) } - p.Outputf("Created credentials group %q. Credentials group ID: %s\n\n", *resp.CredentialsGroup.DisplayName, *resp.CredentialsGroup.CredentialsGroupId) - p.Outputf("URN: %s\n", *resp.CredentialsGroup.Urn) - return nil + return outputResult(p, model, resp) }, } configureFlags(cmd) @@ -100,3 +99,20 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora }) return req } + +func outputResult(p *print.Printer, model *inputModel, resp *objectstorage.CreateCredentialsGroupResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal Object Storage credentials group: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created credentials group %q. Credentials group ID: %s\n\n", *resp.CredentialsGroup.DisplayName, *resp.CredentialsGroup.CredentialsGroupId) + p.Outputf("URN: %s\n", *resp.CredentialsGroup.Urn) + return nil + } +} diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index d9b26ab47..9f6bd38d3 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "time" @@ -79,17 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Object Storage credentials: %w", err) } - expireDate := "Never" - if resp.Expires != nil && *resp.Expires != "" { - expireDate = *resp.Expires - } - - p.Outputf("Created credentials in group %q. Credentials ID: %s\n\n", credentialsGroupLabel, *resp.KeyId) - p.Outputf("Access Key ID: %s\n", *resp.AccessKey) - p.Outputf("Secret Access Key: %s\n", *resp.SecretAccessKey) - p.Outputf("Expire Date: %s\n", expireDate) - - return nil + return outputResult(p, model, credentialsGroupLabel, resp) }, } configureFlags(cmd) @@ -133,3 +124,28 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora }) return req } + +func outputResult(p *print.Printer, model *inputModel, credentialsGroupLabel string, resp *objectstorage.CreateAccessKeyResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal Object Storage credentials: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + expireDate := "Never" + if resp.Expires != nil && *resp.Expires != "" { + expireDate = *resp.Expires + } + + p.Outputf("Created credentials in group %q. Credentials ID: %s\n\n", credentialsGroupLabel, *resp.KeyId) + p.Outputf("Access Key ID: %s\n", *resp.AccessKey) + p.Outputf("Secret Access Key: %s\n", *resp.SecretAccessKey) + p.Outputf("Expire Date: %s\n", expireDate) + + return nil + } +} diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index 1a6affef6..56c2f1d4d 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -76,20 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create OpenSearch credentials: %w", err) } - p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) // The username field cannot be set by the user so we only display it if it's not returned empty - username := *resp.Raw.Credentials.Username - if username != "" { - p.Outputf("Username: %s\n", *resp.Raw.Credentials.Username) - } - if model.HidePassword { - p.Outputf("Password: \n") - } else { - p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) - } - p.Outputf("Host: %s\n", *resp.Raw.Credentials.Host) - p.Outputf("Port: %d\n", *resp.Raw.Credentials.Port) - p.Outputf("URI: %s\n", *resp.Uri) - return nil + return outputResult(p, model, instanceLabel, resp) }, } configureFlags(cmd) @@ -121,3 +109,31 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. req := apiClient.CreateCredentials(ctx, model.ProjectId, model.InstanceId) return req } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *opensearch.CredentialsResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal OpenSearch credentials: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) // The username field cannot be set by the user so we only display it if it's not returned empty + username := *resp.Raw.Credentials.Username + if username != "" { + p.Outputf("Username: %s\n", *resp.Raw.Credentials.Username) + } + if model.HidePassword { + p.Outputf("Password: \n") + } else { + p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) + } + p.Outputf("Host: %s\n", *resp.Raw.Credentials.Host) + p.Outputf("Port: %d\n", *resp.Raw.Credentials.Port) + p.Outputf("URI: %s\n", *resp.Uri) + return nil + } +} diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index b3cb95b18..6dac5124b 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "errors" "fmt" "strings" @@ -125,12 +126,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) - return nil + return outputResult(p, model, projectLabel, instanceId, resp) }, } configureFlags(cmd) @@ -247,3 +243,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient openSearchCl }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId string, resp *opensearch.CreateInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal OpenSearch instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) + return nil + } +} diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index 1007bf548..01fc2fee8 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -2,6 +2,7 @@ package clone import ( "context" + "encoding/json" "fmt" "time" @@ -107,13 +108,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Cloned" - if model.Async { - operationState = "Triggered cloning of" - } - - p.Info("%s instance from instance %q. New Instance ID: %s\n", operationState, instanceLabel, instanceId) - return nil + return outputResult(p, model, instanceLabel, instanceId, resp) }, } configureFlags(cmd) @@ -198,3 +193,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFl }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel, instanceId string, resp *postgresflex.CloneInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal PostgresFlex instance clone: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Cloned" + if model.Async { + operationState = "Triggered cloning of" + } + p.Info("%s instance from instance %q. New Instance ID: %s\n", operationState, instanceLabel, instanceId) + return nil + } +} diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index c9141c17f..b36651921 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "errors" "fmt" @@ -131,12 +132,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) - return nil + return outputResult(p, model, projectLabel, instanceId, resp) }, } configureFlags(cmd) @@ -264,3 +260,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFl }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId string, resp *postgresflex.CreateInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal PostgresFlex instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) + return nil + } +} diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index 118e0a640..30fabc04b 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -2,6 +2,7 @@ package update import ( "context" + "encoding/json" "errors" "fmt" @@ -116,12 +117,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Updated" - if model.Async { - operationState = "Triggered update of" - } - p.Info("%s instance %q\n", operationState, instanceLabel) - return nil + return outputResult(p, model, instanceLabel, resp) }, } configureFlags(cmd) @@ -298,3 +294,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFl }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *postgresflex.PartialUpdateInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal PostgresFlex instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Updated" + if model.Async { + operationState = "Triggered update of" + } + p.Info("%s instance %q\n", operationState, instanceLabel) + return nil + } +} diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index 10f57edf1..ca6b3d589 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -87,17 +88,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("create PostgreSQL Flex user: %w", err) } - user := resp.Item - p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, *user.Id) - p.Outputf("Username: %s\n", *user.Username) - p.Outputf("Password: %s\n", *user.Password) - p.Outputf("Roles: %v\n", *user.Roles) - p.Outputf("Host: %s\n", *user.Host) - p.Outputf("Port: %d\n", *user.Port) - p.Outputf("URI: %s\n", *user.Uri) - - return nil + return outputResult(p, model, instanceLabel, resp) }, } @@ -138,3 +130,27 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresfle }) return req } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *postgresflex.CreateUserResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal PostgresFlex user: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + user := resp.Item + p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, *user.Id) + p.Outputf("Username: %s\n", *user.Username) + p.Outputf("Password: %s\n", *user.Password) + p.Outputf("Roles: %v\n", *user.Roles) + p.Outputf("Host: %s\n", *user.Host) + p.Outputf("Port: %d\n", *user.Port) + p.Outputf("URI: %s\n", *user.Uri) + + return nil + } +} diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password.go b/internal/cmd/postgresflex/user/reset-password/reset_password.go index b18ad672b..f69b409ed 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -2,6 +2,7 @@ package resetpassword import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -84,11 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("reset PostgreSQL Flex user password: %w", err) } - p.Outputf("Reset password for user %q of instance %q\n\n", userLabel, instanceLabel) - p.Outputf("Username: %s\n", *user.Item.Username) - p.Outputf("New password: %s\n", *user.Item.Password) - p.Outputf("New URI: %s\n", *user.Item.Uri) - return nil + return outputResult(p, model, userLabel, instanceLabel, user) }, } @@ -122,3 +119,22 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresfle req := apiClient.ResetUser(ctx, model.ProjectId, model.InstanceId, model.UserId) return req } + +func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel string, user *postgresflex.ResetUserResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(user, "", " ") + if err != nil { + return fmt.Errorf("marshal PostgresFlex user: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Reset password for user %q of instance %q\n\n", userLabel, instanceLabel) + p.Outputf("Username: %s\n", *user.Item.Username) + p.Outputf("New password: %s\n", *user.Item.Password) + p.Outputf("New URI: %s\n", *user.Item.Uri) + return nil + } +} diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index cfcbf1c06..8134ceb23 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "regexp" @@ -81,8 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create project: %w", err) } - p.Outputf("Created project under the parent with ID %q. Project ID: %s\n", *model.ParentId, *resp.ProjectId) - return nil + return outputResult(p, model, resp) }, } configureFlags(cmd) @@ -176,3 +176,19 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *resourceman return req, nil } + +func outputResult(p *print.Printer, model *inputModel, resp *resourcemanager.ProjectResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal project: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created project under the parent with ID %q. Project ID: %s\n", *model.ParentId, *resp.ProjectId) + return nil + } +} diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index bb7c21ae9..95679181b 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -76,21 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create RabbitMQ credentials: %w", err) } - p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) - // The username field cannot be set by the user so we only display it if it's not returned empty - username := *resp.Raw.Credentials.Username - if username != "" { - p.Outputf("Username: %s\n", *resp.Raw.Credentials.Username) - } - if model.HidePassword { - p.Outputf("Password: \n") - } else { - p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) - } - p.Outputf("Host: %s\n", *resp.Raw.Credentials.Host) - p.Outputf("Port: %d\n", *resp.Raw.Credentials.Port) - p.Outputf("URI: %s\n", *resp.Uri) - return nil + return outputResult(p, model, instanceLabel, resp) }, } configureFlags(cmd) @@ -122,3 +109,32 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *rabbitmq.AP req := apiClient.CreateCredentials(ctx, model.ProjectId, model.InstanceId) return req } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *rabbitmq.CredentialsResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal RabbitMQ credentials: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) + // The username field cannot be set by the user so we only display it if it's not returned empty + username := *resp.Raw.Credentials.Username + if username != "" { + p.Outputf("Username: %s\n", *resp.Raw.Credentials.Username) + } + if model.HidePassword { + p.Outputf("Password: \n") + } else { + p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) + } + p.Outputf("Host: %s\n", *resp.Raw.Credentials.Host) + p.Outputf("Port: %d\n", *resp.Raw.Credentials.Port) + p.Outputf("URI: %s\n", *resp.Uri) + return nil + } +} diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index d931f44fc..da5c6de2c 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "errors" "fmt" "strings" @@ -125,12 +126,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) - return nil + return outputResult(p, model, projectLabel, instanceId, resp) }, } configureFlags(cmd) @@ -247,3 +243,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient rabbitMQClie }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId string, resp *rabbitmq.CreateInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal RabbitMQ instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) + return nil + } +} diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index db39a1e72..43cf118f7 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -76,21 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Redis credentials: %w", err) } - p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) - // The username field cannot be set by the user so we only display it if it's not returned empty - username := *resp.Raw.Credentials.Username - if username != "" { - p.Outputf("Username: %s\n", *resp.Raw.Credentials.Username) - } - if model.HidePassword { - p.Outputf("Password: \n") - } else { - p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) - } - p.Outputf("Host: %s\n", *resp.Raw.Credentials.Host) - p.Outputf("Port: %d\n", *resp.Raw.Credentials.Port) - p.Outputf("URI: %s\n", *resp.Uri) - return nil + return outputResult(p, model, instanceLabel, resp) }, } configureFlags(cmd) @@ -122,3 +109,32 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *redis.APICl req := apiClient.CreateCredentials(ctx, model.ProjectId, model.InstanceId) return req } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *redis.CredentialsResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal Redis credentials: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) + // The username field cannot be set by the user so we only display it if it's not returned empty + username := *resp.Raw.Credentials.Username + if username != "" { + p.Outputf("Username: %s\n", *resp.Raw.Credentials.Username) + } + if model.HidePassword { + p.Outputf("Password: \n") + } else { + p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) + } + p.Outputf("Host: %s\n", *resp.Raw.Credentials.Host) + p.Outputf("Port: %d\n", *resp.Raw.Credentials.Port) + p.Outputf("URI: %s\n", *resp.Uri) + return nil + } +} diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index 0843bcbdf..1aae7686e 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "errors" "fmt" "strings" @@ -123,12 +124,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) - return nil + return outputResult(p, model, projectLabel, instanceId, resp) }, } configureFlags(cmd) @@ -242,3 +238,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient redisClient) }) return req, nil } + +func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId string, resp *redis.CreateInstanceResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal Redis instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) + return nil + } +} diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index 8d0539d33..7b8c4466a 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -92,8 +93,7 @@ If you want to retry configuring the ACLs, you can do it via: } } - p.Outputf("Created instance for project %q. Instance ID: %s\n", projectLabel, instanceId) - return nil + return outputResult(p, model, projectLabel, instanceId, resp) }, } configureFlags(cmd) @@ -144,3 +144,19 @@ func buildUpdateACLsRequest(ctx context.Context, model *inputModel, instanceId s return req } + +func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId string, resp *secretsmanager.Instance) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal Secrets Manager instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created instance for project %q. Instance ID: %s\n", projectLabel, instanceId) + return nil + } +} diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index da9d4597f..da9ce9bf6 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -84,13 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Secrets Manager user: %w", err) } - p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, *resp.Id) - p.Outputf("Username: %s\n", *resp.Username) - p.Outputf("Password: %s\n", *resp.Password) - p.Outputf("Description: %s\n", *resp.Description) - p.Outputf("Write Access: %t\n", *resp.Write) - - return nil + return outputResult(p, model, instanceLabel, resp) }, } @@ -129,3 +124,24 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *secretsmana }) return req } + +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *secretsmanager.User) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal Secrets Manager user: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, *resp.Id) + p.Outputf("Username: %s\n", *resp.Username) + p.Outputf("Password: %s\n", *resp.Password) + p.Outputf("Description: %s\n", *resp.Description) + p.Outputf("Write Access: %t\n", *resp.Write) + + return nil + } +} diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index aa622af30..ee892103b 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -71,8 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create service account: %w", err) } - p.Outputf("Created service account for project %q. Email: %s\n", projectLabel, *resp.Email) - return nil + return outputResult(p, model, projectLabel, resp) }, } configureFlags(cmd) @@ -105,3 +105,19 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceacco }) return req } + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, serviceAccount *serviceaccount.ServiceAccount) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(serviceAccount, "", " ") + if err != nil { + return fmt.Errorf("marshal service account: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created service account for project %q. Email: %s\n", projectLabel, *serviceAccount.Email) + return nil + } +} diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index 351f1544e..8e9881968 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -76,10 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create access token: %w", err) } - p.Outputf("Created access token for service account %s. Token ID: %s\n\n", model.ServiceAccountEmail, *token.Id) - p.Outputf("Valid until: %s\n", *token.ValidUntil) - p.Outputf("Token: %s\n", *token.Token) - return nil + return outputResult(p, model, token) }, } @@ -131,3 +129,21 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceacco }) return req } + +func outputResult(p *print.Printer, model *inputModel, token *serviceaccount.AccessToken) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(token, "", " ") + if err != nil { + return fmt.Errorf("marshal service account access token: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created access token for service account %s. Token ID: %s\n\n", model.ServiceAccountEmail, *token.Id) + p.Outputf("Valid until: %s\n", *token.ValidUntil) + p.Outputf("Token: %s\n", *token.Token) + return nil + } +} diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 05c5af178..3eafb7099 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -132,12 +132,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Created" - if model.Async { - operationState = "Triggered creation of" - } - p.Outputf("%s cluster for project %q. Cluster name: %s\n", operationState, projectLabel, name) - return nil + return outputResult(p, model, projectLabel, resp) }, } configureFlags(cmd) @@ -179,3 +174,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie req = req.CreateOrUpdateClusterPayload(*model.Payload) return req } + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *ske.Cluster) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal SKE cluster: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s cluster for project %q. Cluster name: %s\n", operationState, projectLabel, *resp.Name) + return nil + } +} diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index e7551accb..9c477c8e2 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -104,12 +104,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - operationState := "Updated" - if model.Async { - operationState = "Triggered update of" - } - p.Info("%s cluster %q\n", operationState, model.ClusterName) - return nil + return outputResult(p, model, resp) }, } configureFlags(cmd) @@ -151,3 +146,23 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie req = req.CreateOrUpdateClusterPayload(model.Payload) return req } + +func outputResult(p *print.Printer, model *inputModel, resp *ske.Cluster) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal SKE cluster: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Updated" + if model.Async { + operationState = "Triggered update of" + } + p.Info("%s cluster %q\n", operationState, model.ClusterName) + return nil + } +} diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index 3e8d29e38..322f1a853 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -2,6 +2,7 @@ package create import ( "context" + "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -107,9 +108,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("write kubeconfig file: %w", err) } - p.Outputf("Created kubeconfig file for cluster %s in %q, with expiration date %v (UTC)\n", model.ClusterName, kubeconfigPath, *resp.ExpirationTimestamp) - - return nil + return outputResult(p, model, kubeconfigPath, resp) }, } configureFlags(cmd) @@ -161,3 +160,20 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie return req.CreateKubeconfigPayload(payload), nil } + +func outputResult(p *print.Printer, model *inputModel, kubeconfigPath string, resp *ske.Kubeconfig) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal SKE Kubeconfig: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created kubeconfig file for cluster %s in %q, with expiration date %v (UTC)\n", model.ClusterName, kubeconfigPath, *resp.ExpirationTimestamp) + + return nil + } +}